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