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