]> Creatis software - gdcm.git/blob - src/gdcmJpegIdo.cxx
* src/gdcmFile.cxx : bug fix under Window after JPR commit
[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 lengh
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             jpg->lSof.NbComponent=fgetc(jpg->infp); 
170
171             jpg->lSof.SofTabPos=ftell(jpg->infp);
172
173             isLossLess=1; // TRUE
174          }
175
176          if (el==0xC4) {
177             ClbJpegFillHuffTable(jpg);
178          }
179          if (el==0xDA) {
180             jpg->lSos.CompCount=fgetc(jpg->infp);
181             for (tp=0;tp<jpg->lSos.CompCount;tp++) {
182                jpg->lSos.CompId=fgetc(jpg->infp);
183                jpg->lSos.CompDc=fgetc(jpg->infp);
184             }
185             jpg->lSos.SpectralSelStart=fgetc(jpg->infp);
186             jpg->lSos.SpectralSelEnd=fgetc(jpg->infp);
187             jpg->lSos.SuccessiveAp=fgetc(jpg->infp);
188             jpg->lSos.Sospttrans=(jpg->lSos.SuccessiveAp & 16);
189             HeaderEnd=1;
190          }
191          if (el==0xDD) {
192             l1=fgetc(jpg->infp);
193             l2=fgetc(jpg->infp);
194             jpg->RestartInterval=(l1*256)+l2;
195          }
196
197          fseek(jpg->infp,(ouca+sztag),0);
198       }
199    }
200
201    if (!isLossLess) {
202       printf("NOT isLossLess\n");
203       return 0;
204    }
205    return 1;
206 }
207
208 static int ClbJpegReadBit(ClbJpeg *jpg) {
209         int r=0;
210         unsigned char c;
211         if(jpg->PosCurBit>8) // need lire octet suivant
212         {
213                 jpg->ValCurByte=fgetc(jpg->infp);
214                 if (jpg->ValCurByte==0xFF)
215                 {
216                         c=fgetc(jpg->infp);// est 00 ou restart marker: a skiper
217                         if (c!=0)
218                         {
219                                 jpg->ValCurByte=fgetc(jpg->infp);
220                                 jpg->PosCurBit=1;
221                                 jpg->MarkerFound=1;
222                                 return 0; 
223                         }
224                 }
225                 jpg->PosCurBit=2;
226                 return (jpg->ValCurByte>>7);
227         }
228         else
229         {
230                 r=(1&(jpg->ValCurByte>>(8-jpg->PosCurBit)));
231                 jpg->PosCurBit+=1;
232                 return r;
233         }
234 }
235
236
237 static BOOL ClbJpegDecodeData(ClbJpeg *jpg)
238 {
239         int iX,iY;
240         int lbInc=0;
241         unsigned int mask; 
242           
243         int lPredicted=(1<<(jpg->lSof.precision-1-jpg->lSos.Sospttrans));
244
245         jpg->ValCurByte=jpg->lSos.SuccessiveAp;
246         jpg->PosCurBit=9;
247         
248         if (jpg->lSof.precision==8)
249                 mask=0xFF;
250         if (jpg->lSof.precision==12)
251                 mask=0xFFF;
252         if (jpg->lSof.precision==16)
253                 mask=0xFFFF;
254
255 //printf("jpg->lSof.precision : %d\n",jpg->lSof.precision );
256 //printf("sizeof(*jpg->DataImg) : %d\n",sizeof(*jpg->DataImg) );
257
258          jpg->DataImg=(int*)malloc(jpg->lSof.Himg*jpg->lSof.Wimg*sizeof(*jpg->DataImg));
259         memset( jpg->DataImg,0,(jpg->lSof.Himg * jpg->lSof.Wimg * sizeof(*jpg->DataImg)));
260
261         if (!jpg->RestartInterval)
262         {
263         //printf("il N'y a PAS un define interval\n");
264                 for(iX=0;iX<jpg->lSof.Wimg;iX++) // lit première ligne
265                 {
266                         lbInc+=1;
267                         if (lbInc>1)
268                                 lPredicted= jpg->DataImg[lbInc-1];
269                          jpg->DataImg[lbInc]=lPredicted+ClbJpegDecodeDiff(jpg);
270
271                         if (  jpg->DataImg[lbInc] > ((1<<(jpg->lSof.precision))-1) )
272                                  jpg->DataImg[lbInc]= jpg->DataImg[lbInc]&mask;
273                         if ( jpg->DataImg[lbInc]<0) 
274                                  jpg->DataImg[lbInc]= jpg->DataImg[lbInc]&mask;
275                 }
276
277                 for (iY=1;iY<jpg->lSof.Himg;iY++) //lit la suite
278                 {
279                         lbInc+=1;
280                         if (lbInc>(jpg->lSof.Himg*jpg->lSof.Wimg-1)) break;
281                         lPredicted= jpg->DataImg[lbInc-jpg->lSof.Wimg]; // se base % premier é ligne d'avant
282                          jpg->DataImg[lbInc]=lPredicted+ClbJpegDecodeDiff(jpg);
283
284                         if (  jpg->DataImg[lbInc] > ((1<<(jpg->lSof.precision))-1) ) 
285                                  jpg->DataImg[lbInc]= jpg->DataImg[lbInc]&mask;
286                         if ( jpg->DataImg[lbInc]<0) 
287                                  jpg->DataImg[lbInc]= jpg->DataImg[lbInc]&mask;
288
289                         for(iX=1;iX<jpg->lSof.Wimg;iX++)
290                         {
291                                 lbInc+=1;
292                                 if (lbInc>(jpg->lSof.Himg*jpg->lSof.Wimg-1)) break;
293                                 if (jpg->lSos.SpectralSelStart==7) // si spectral
294                                         lPredicted=( jpg->DataImg[lbInc-1]+ jpg->DataImg[lbInc-jpg->lSof.Wimg])>>1;
295                                 else
296                                         lPredicted= jpg->DataImg[lbInc-1];              // se base%pixel juste avant
297                                  jpg->DataImg[lbInc]=lPredicted+ClbJpegDecodeDiff(jpg);
298
299                                 if (  jpg->DataImg[lbInc] > ((1<<(jpg->lSof.precision))-1) ) 
300                                          jpg->DataImg[lbInc]= jpg->DataImg[lbInc]&mask;
301                                 if ( jpg->DataImg[lbInc]<0) 
302                                          jpg->DataImg[lbInc]= jpg->DataImg[lbInc]&mask;
303
304                         }
305                 }
306         }
307         else // il y a un define interval
308         {
309                 //printf("il y a un define interval\n");
310                 while(1)
311                 {
312                         jpg->MarkerFound=0;
313                         lPredicted=(1<<(jpg->lSof.precision - 1 - jpg->lSos.Sospttrans));
314                         for (iY=0;iY<jpg->RestartInterval;iY++) 
315                         {
316                                  jpg->DataImg[lbInc]=lPredicted+ClbJpegDecodeDiff(jpg);
317
318                                 if (  jpg->DataImg[lbInc] > ((1<<(jpg->lSof.precision))-1) ) 
319                                          jpg->DataImg[lbInc]= jpg->DataImg[lbInc]&mask;
320                                 if ( jpg->DataImg[lbInc]<0) 
321                                          jpg->DataImg[lbInc]= jpg->DataImg[lbInc]&mask;
322
323                                 lbInc+=1;
324                                 if (lbInc>(jpg->lSof.Himg*jpg->lSof.Wimg-1)) return 1;
325
326                                 if (jpg->lSos.SpectralSelStart==7) // si spectral
327                                         lPredicted=( jpg->DataImg[lbInc-1]+ jpg->DataImg[lbInc-jpg->lSof.Wimg])>>1;
328                                 else
329                                         lPredicted= jpg->DataImg[lbInc-1];
330                         }
331                         while (!jpg->MarkerFound)
332                         {
333                                 ClbJpegReadBit(jpg); // skip bits restant avant restart marker
334                         }
335                 }
336         }
337         return 1;
338 }
339
340 static int ClbJpegDecodeDiff(ClbJpeg *jpg) {
341    int lInput;
342    int lInputBits;
343    int lHufVal;
344    int lDiff;
345    int lI;
346    int resultat;
347    lHufVal = 666;
348    lInput = 0;
349    lInputBits = 0;
350
351    while (1) {
352       lInputBits+=1;
353       lInput=(lInput<<1)+ClbJpegReadBit(jpg);
354       if (jpg->RawDHT[lInputBits]!=0) {
355          for(lI=jpg->RawDHTstart[lInputBits];lI<(jpg->RawDHTstart[lInputBits]+jpg->RawDHT[lInputBits]);lI++) {
356             if (lInput==jpg->lHuffTable[lI].HufCode)
357                lHufVal=jpg->lHuffTable[lI].HufVal;
358          }
359       }
360       if (lInputBits>=jpg->MaxHuffSz)
361          lHufVal=jpg->MaxHuffVal;
362       if (lHufVal<255) break;
363    }
364    if (lHufVal==0) resultat= 0;
365
366    if ( (lHufVal>0) && (lHufVal<16)) {
367       lDiff=0;
368       if( ClbJpegReadBit(jpg)==1) {
369          for (lI=1;lI<lHufVal;lI++) {
370             lDiff=(lDiff<<1)+ClbJpegReadBit(jpg);
371          }
372          resultat= (lDiff+(1<<(lHufVal-1)));
373       } else {
374          for (lI=1;lI<lHufVal;lI++)
375             lDiff=(lDiff<<1)+1-ClbJpegReadBit(jpg);
376          resultat= -(lDiff+(1<<(lHufVal-1)));
377       }
378    }
379    return resultat;     
380 }