]> Creatis software - gdcm.git/blob - src/gdcmjpegls/Decoder/decoder.c
COMP: Tons of warnings fix...cannot believe how poorly written this was
[gdcm.git] / src / gdcmjpegls / Decoder / decoder.c
1 /* SPMG/JPEG-LS IMPLEMENTATION V.2.1
2    =====================================
3    These programs are Copyright (c) University of British Columbia. All right reserved.
4    They may be freely redistributed in their entirety provided that this copyright
5    notice is not removed. THEY MAY NOT BE SOLD FOR PROFIT OR INCORPORATED IN
6    COMMERCIAL PROGRAMS WITHOUT THE WRITTEN PERMISSION OF THE COPYRIGHT HOLDER.
7    Each program is provided as is, without any express or implied warranty,
8    without even the warranty of fitness for a particular purpose.
9
10    =========================================================
11    THIS SOFTWARE IS BASED ON HP's implementation of jpeg-ls:
12    =========================================================
13
14    LOCO-I/JPEG-LS IMPLEMENTATION V.0.90
15    -------------------------------------------------------------------------------
16    (c) COPYRIGHT HEWLETT-PACKARD COMPANY, 1995-1999.
17         HEWLETT-PACKARD COMPANY ("HP") DOES NOT WARRANT THE ACCURACY OR
18    COMPLETENESS OF THE INFORMATION GIVEN HERE.  ANY USE MADE OF, OR
19    RELIANCE ON, SUCH INFORMATION IS ENTIRELY AT USER'S OWN RISK.
20         BY DOWNLOADING THE LOCO-I/JPEG-LS COMPRESSORS/DECOMPRESSORS
21    ("THE SOFTWARE") YOU AGREE TO BE BOUND BY THE TERMS AND CONDITIONS
22    OF THIS LICENSING AGREEMENT.
23         YOU MAY DOWNLOAD AND USE THE SOFTWARE FOR NON-COMMERCIAL PURPOSES
24    FREE OF CHARGE OR FURTHER OBLIGATION.  YOU MAY NOT, DIRECTLY OR
25    INDIRECTLY, DISTRIBUTE THE SOFTWARE FOR A FEE, INCORPORATE THIS
26    SOFTWARE INTO ANY PRODUCT OFFERED FOR SALE, OR USE THE SOFTWARE
27    TO PROVIDE A SERVICE FOR WHICH A FEE IS CHARGED.
28         YOU MAY MAKE COPIES OF THE SOFTWARE AND DISTRIBUTE SUCH COPIES TO
29    OTHER PERSONS PROVIDED THAT SUCH COPIES ARE ACCOMPANIED BY
30    HEWLETT-PACKARD'S COPYRIGHT NOTICE AND THIS AGREEMENT AND THAT
31    SUCH OTHER PERSONS AGREE TO BE BOUND BY THE TERMS OF THIS AGREEMENT.
32         THE SOFTWARE IS NOT OF PRODUCT QUALITY AND MAY HAVE ERRORS OR DEFECTS.
33    THE JPEG-LS STANDARD IS STILL UNDER DEVELOPMENT. THE SOFTWARE IS NOT A
34    FINAL OR FULL IMPLEMENTATION OF THE STANDARD.  HP GIVES NO EXPRESS OR
35    IMPLIED WARRANTY OF ANY KIND AND ANY IMPLIED WARRANTIES OF
36    MERCHANTABILITY AND FITNESS FOR PURPOSE ARE DISCLAIMED.
37         HP SHALL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL,
38    OR CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE SOFTWARE.
39    -------------------------------------------------------------------------------
40 */
41
42 /* decoder.c --- the main module, argument parsing, file I/O 
43  *
44  * Initial code by Alex Jakulin,  Aug. 1995
45  *
46  * Modified and optimized: Gadiel Seroussi, October 1995
47  *
48  * Color Enhancement: Guillermo Sapiro, August 1996
49  *
50  * Modified and added Restart marker and input tables by:
51  * David Cheng-Hsiu Chu, and Ismail R. Ismail march 1999
52  */
53
54 #include "global.h"
55 #include <string.h>
56 #include "jpegmark.h"
57
58 #define  PGMNAME PGMPREFIX "d"
59 #define  EPGMNAME PGMPREFIX "e"
60
61 static char *banner="\n\
62 =============================================\n\
63 SPMG/JPEG-LS DECOMPRESSOR " JPEGLSVERSION "\n\
64 =============================================\n\
65 These programs are Copyright (c) University of British Columbia.\n\
66 All rights reserved. They may be freely redistributed in their\n\
67 entirety provided that this copyright  notice is not removed.\n\
68 They may not be sold for profit or incorporated in commercial\n\
69 programs without the written permission of the copyright holder.\n\
70 Each program is provided as is, without any express or implied\n\
71 warranty, without even the warranty of fitness for a particular\n\
72 purpose.\n\
73 \n\
74 =========================================================\n\
75 THIS SOFTWARE IS BASED ON HP's implementation of jpeg-ls:\n\
76 =========================================================\n\
77 (c) COPYRIGHT HEWLETT-PACKARD COMPANY, 1995-1999.\n";
78
79 pixel *pscanline, *cscanline, *pscanl0, *cscanl0;
80 pixel *c_pscanline[MAX_COMPONENTS], *c_cscanline[MAX_COMPONENTS],
81       *c_pscanl0[MAX_COMPONENTS],  *c_cscanl0[MAX_COMPONENTS];
82
83 jpeg_ls_header *head_frame, *head_scan[MAX_SCANS];
84
85 int columns, rows, components,
86     samplingx[MAX_COMPONENTS], samplingy[MAX_COMPONENTS];
87 int c_columns[MAX_COMPONENTS], c_rows[MAX_COMPONENTS];
88 int whose_max_size_columns, whose_max_size_rows, number_of_scans;
89 int  color_mode;
90 int shift;        /* Shift value for sparse images */
91 int  got_lse;      /* got an LSE marker */
92 int got_table;      /* got a mapping table */
93 int got_restart;    /* got a restart marker indicatino */
94 int restart_interval;  /* the restart interval */
95 int multi;          /* if the files are separate */
96 int  application_header;  /* application bytes in the header */
97
98 int lossy;            /* Indicates if in lossy mode or not */
99 int bpp16;            /* Indicates if 16 bits per pixel mode or not */
100 int lutmax;            /* lutmax is either 256 or 4501 */
101
102
103
104
105 /* reset */
106 #ifndef FIXRESET
107 int  RESET;
108 #endif
109
110
111 /* alphabet size */
112 #ifndef FIXALPHA
113 int     alpha,     /* alphabet size */
114   ceil_half_alpha; /* ceil(alpha/2) */
115 #endif
116
117 #ifdef POW2
118 int     highmask;
119 #endif
120
121 void usage();
122
123
124
125
126
127 /* Write one row of pixel values */
128 inline void write_one_line(pixel* line, int cols, FILE* outfile)
129 {
130
131   int i, index;
132   unsigned int* maptable;
133       
134   /* No mapping tables used */
135   if(!(head_scan[0]->need_table))
136     if (bpp16==FALSE)
137     {
138       unsigned char* line8;
139       line8 = (unsigned char*)safealloc(cols);
140   
141       for (i=0; i< cols; i++)
142         *(line8+i)=ENDIAN8(*(line+i));
143     
144       fwrite(line8, sizeof(unsigned char), cols, outfile);
145
146       free(line8);
147     } else {
148       fwrite(line, sizeof(short), cols, outfile);
149     }
150
151   /* Mapping tables used */
152   else
153   {
154     if (bpp16==FALSE)
155     {
156       /* Write one byte per table entry */
157       if (head_scan[0]->Wt == 1)
158       {
159         unsigned char* line8;
160         line8 = (unsigned char*)safealloc(cols);  /* If don't have 2, it mallocs over the table? */
161
162         maptable = head_scan[0]->TABLE[head_scan[0]->TID];
163
164         for (i=0; i<cols; i++)
165         {
166           index = *(line+i);
167           *(line8+i) = ENDIAN8(maptable[index]);
168         }
169
170         fwrite(line8, sizeof(unsigned char), cols, outfile);
171
172         free(line8);
173       }
174       /* Write two bytes per table entry */
175       else if (head_scan[0]->Wt == 2)
176       {
177         unsigned short* line16;
178         line16 = (unsigned short*)safealloc(cols*2);
179
180         maptable = head_scan[0]->TABLE[head_scan[0]->TID];
181
182         for (i=0; i<cols; i++)
183         {
184           index = *(line+i);
185           *(line16+i) = (unsigned short) maptable[index];
186         }
187
188         fwrite(line16, sizeof(short), cols, outfile);
189
190         free(line16);
191       }
192       /* Write three bytes per table entry */
193       else if (head_scan[0]->Wt == 3)
194       {
195         unsigned char* line8_3;
196         line8_3 = (unsigned char*)safealloc(cols*3);
197
198         maptable = head_scan[0]->TABLE[head_scan[0]->TID];
199
200         for (i=0; i<cols; i++)
201         {
202           index = *(line+i);
203           *(line8_3 + (i*3)) =  (unsigned char) (maptable[index] >> 16);
204           *(line8_3 + (i*3) + 1) = (unsigned char) (maptable[index] >> 8);
205           *(line8_3 + (i*3) + 2) = (unsigned char) (maptable[index]);
206         }
207
208         fwrite(line8_3, sizeof(char), cols*3, outfile);
209
210         free(line8_3);
211       }
212
213           
214     /* Can't do 16 bit index values */
215     }
216     else
217     {
218       fprintf(stderr, "Sorry, mapping tables are only supported for 8 bpp images in this implementation.\n");
219       exit(0);
220     }
221   }
222
223
224 }
225
226
227
228
229
230 void initbuffers(int multi, int comp) {
231
232   int  i;
233
234   if (multi)     /* Output to several files */
235
236     for (i=0;i<comp;i++) {
237
238       c_pscanl0[i] = (pixel *)safecalloc((c_columns[i]+LEFTMARGIN+RIGHTMARGIN), sizeof(pixel) );
239       c_cscanl0[i] = (pixel *)safecalloc((c_columns[i]+LEFTMARGIN+RIGHTMARGIN), sizeof(pixel) );
240
241       /* Adjust scan line pointers taking into account the margins,
242          and also the fact that indexing for scan lines starts from 1
243        */
244       c_pscanline[i] = c_pscanl0[i] + (LEFTMARGIN-1);
245       c_cscanline[i] = c_cscanl0[i] + (LEFTMARGIN-1);
246     }
247
248   else {      /* Output to a single file */
249
250     pscanl0 = (pixel *)safecalloc(components*(columns+LEFTMARGIN+RIGHTMARGIN), sizeof(pixel) );
251     cscanl0 = (pixel *)safecalloc(components*(columns+LEFTMARGIN+RIGHTMARGIN), sizeof(pixel) );
252
253     /* Adjust scan line pointers taking into account the margins,
254        and also the fact that indexing for scan lines starts from 1
255        (this will probably have to be changed in the future) 
256      */
257     pscanline = pscanl0 + components*(LEFTMARGIN-1);
258     cscanline = cscanl0 + components*(LEFTMARGIN-1);
259   }
260
261     createzeroLUT();
262
263 }
264
265 void swaplines()
266 {
267   pixel *temp;
268   temp = pscanl0;
269   pscanl0 = cscanl0;
270   cscanl0 = temp;
271   pscanline = pscanl0 + components*(LEFTMARGIN-1);
272   cscanline = cscanl0 + components*(LEFTMARGIN-1);
273 }
274
275 void c_swaplines(int i)
276 {
277   pixel *temp;
278   temp = c_pscanl0[i];
279   c_pscanl0[i] = c_cscanl0[i];
280   c_cscanl0[i] = temp;
281   c_pscanline[i] = c_pscanl0[i] + (LEFTMARGIN-1);
282   c_cscanline[i] = c_cscanl0[i] + (LEFTMARGIN-1);
283 }
284
285 void closebuffers(int multi) {
286
287   int     i;
288
289   fclose(in);
290   if (multi==0)
291      fclose(out);
292         else
293            for (i=0;i<components;i++)
294          fclose(c_out[i]);
295
296         free(pscanl0);
297         free(cscanl0);
298 }
299
300
301
302
303 int initialize(int argc, char *argv[]) {
304   char *infilename = NULL,
305     *outfilename = OUTFILE ".out",
306     *c_outfilename[MAX_COMPONENTS],
307     *color_mode_string;
308   int i, max_samp_columns, max_samp_rows, mk, n_s,
309     end_of_seek=0,
310     seek_return,
311     alpha0,
312     gotinf = 0,
313     gotoutf = 0,
314     out_files=0;
315   int pos;   /* position in the file, after the header */
316
317   for (i=0;i<MAX_COMPONENTS;i++) {
318     c_outfilename[i]=malloc(strlen(OUTFILE)+20);
319     sprintf(c_outfilename[i],"%s%d.out",OUTFILE,i+1);
320   }
321
322   multi=1;
323   for ( i=1; i<argc; i++ )
324     if ( argv[i][0] == '-' )
325     {
326       switch ( argv[i][1] ) {
327
328       case 'i':
329         infilename  = argv[i]+2;
330         gotinf = 1;
331         break;
332
333       case 'o':
334         outfilename = c_outfilename[out_files++] = argv[i]+2;
335         gotoutf = 1;
336         break;
337
338       case 'P':
339         multi=0;
340         break;
341
342       case 'v':
343         if ( sscanf(argv[i],"-v%d",&verbose) != 1 )
344           verbose=2;
345         break;
346
347       default:
348         usage();
349         exit(0);
350       }
351     }
352       else {
353       if ( ! gotinf ) {
354         infilename = argv[i];
355         gotinf = 1;
356       }
357       else if ( ! gotoutf )
358         outfilename = c_outfilename[out_files++] = argv[i];
359     }
360       
361   if ( verbose < 1 )
362       verbose = 1;  /* at least the banner will show */
363
364   if ((!multi) && (out_files>1)) {
365     fprintf(stderr,"\nERROR: Only 1 output file expected with -P option.\nThis option is valid only for line/pixel interleaved and not subsampled.\n");
366     exit(10);
367   }
368
369   /* Open in file */
370   if ( infilename == NULL ) {
371     usage();
372     exit(0);
373   }
374   else {
375     if ( strcmp(infilename,"-")==0 )
376       in = stdin;
377     else if ( (in=fopen(infilename,"rb")) == NULL ) {
378       perror(infilename);
379       exit(10);
380     }
381   }
382
383   /* Read the compressed image frame header */
384   bufiinit(in);
385
386   head_frame = (jpeg_ls_header *) safecalloc(1,sizeof(jpeg_ls_header));
387
388   for (n_s=0;n_s<MAX_SCANS;n_s++) {
389     head_scan[n_s] = (jpeg_ls_header *) safecalloc(1,sizeof(jpeg_ls_header));
390     head_scan[n_s]->T1=head_scan[n_s]->T2=head_scan[n_s]->T3=0;
391     head_scan[n_s]->RES = DEFAULT_RESET;
392   }
393
394   /* Read SOI */
395   seek_return = seek_marker(in,&mk);
396   if (seek_return == EOF) {
397     fprintf(stderr,"*** Premature End of File seeking SOI\n");
398     exit(10);
399   }
400   else {
401     pos = seek_return;
402     if (mk != SOI) {
403       fprintf(stderr,"Marker %04x found: first marker must be SOI (%04x) in this implementation\n", mk, SOI);
404       exit(10);
405     }
406   }
407
408   /* Read SOF_LS */
409   seek_return = seek_marker(in,&mk);
410   if (seek_return == EOF) {
411     fprintf(stderr,"*** Premature End of File seeking SOF_LS\n");
412     exit(10);
413   }
414   else {
415     pos += seek_return; /* Read SOF_LS */
416     if (mk != SOF_LS) {
417       fprintf(stderr,"Marker %04x found: second marker must be SOF_LS (%04x) in this implementation\n", mk, SOF_LS);
418       exit(10);
419     }
420   }
421
422   /* Read the frame header (SOF) */
423   seek_return = read_jpegls_frame(in,head_frame);
424   if (seek_return == EOF) {
425     fprintf(stderr,"*** Premature End of File reading frame header\n");
426     exit(10);
427   }
428   else
429     pos += seek_return;
430
431   head_scan[0]->alp = head_frame->alp;    /* default alpha */
432
433
434   /* LSE Extension header */
435   /* This version supports only 2 extension headers, and 1 set of
436      parameters for all the scans */
437   got_lse = 0;
438   head_scan[0]->need_table = 0;
439
440   while (!end_of_seek)
441   {
442     seek_return=seek_marker(in, &mk);
443     if (seek_return == EOF) {
444       fprintf(stderr,"*** Premature End of File seeking SOS or LSE marker\n");
445       exit(10);
446     }
447     pos +=seek_return;
448
449
450     switch(mk)
451     {
452     case LSE:
453       seek_return = read_jpegls_extmarker(in, head_scan[0]);
454       if (seek_return == EOF) {
455         fprintf(stderr,"*** Premature End of File\n");
456         exit(10);
457       }
458       pos += seek_return;
459       got_lse = 1;
460       break;
461     
462     case DRI:
463       seek_return = read_jpegls_restartmarker(in, head_scan[0]);
464       pos += seek_return;
465       got_restart = 1;
466       restart_interval = head_scan[0]->restart_interval;
467       break;
468     
469     case SOS:
470       end_of_seek=1;  
471       break;
472     }
473   }
474   /* End of extension header */
475
476
477
478   /* Read the scan header*/
479   seek_return = read_jpegls_scan(in,head_scan[0]);
480   if (seek_return == EOF) {
481     fprintf(stderr,"*** Premature End of File reading scan marker segment\n");
482     exit(10);
483   }
484   pos+=seek_return;
485
486   shift=head_scan[0]->shift;
487   if (shift!=0) {
488     fprintf(stderr,"Got shift = %d != 0 : not implemented.\n",shift);
489     exit(10);
490   }
491
492   NEAR=head_scan[0]->NEAR;
493   color_mode=head_scan[0]->color_mode;
494   columns=head_frame->columns;
495   rows=head_frame->rows;
496   alpha0=head_scan[0]->alp;
497   head_frame->alp = alpha0;
498   components=head_frame->comp;
499
500   if (color_mode==PLANE_INT) 
501     number_of_scans=components;
502   else
503     number_of_scans=1;
504
505   set_thresholds(head_scan[0]->alp, head_scan[0]->NEAR, &(head_scan[0]->T1), &(head_scan[0]->T2), &(head_scan[0]->T3));
506   T1=head_scan[0]->T1;
507   T2=head_scan[0]->T2;
508   T3=head_scan[0]->T3;
509
510 #ifndef FIXRESET
511   RESET=head_scan[0]->RES;
512 #else
513   if (head_scan[0]->RES != DEFAULT_RESET) {
514     fprintf(stderr,"ERROR: Version compiled for fixed RESET=%d parameter: got %d\n",DEFAULT_RESET,head_scan[0]->RES);
515     exit(10);
516   }
517 #endif
518
519   /* Check to see if lossless or lossy */
520   if (NEAR == 0)
521     lossy=FALSE;
522   else
523     lossy=TRUE;
524
525   /* Check for 16 or 8 bit mode */
526   if (alpha0 <= MAXA16 && alpha0 > MAXA8)
527   {
528     /* 16 bit */
529     bpp16 = TRUE;
530     lutmax = LUTMAX16;
531   }
532   else if (alpha0 <= MAXA8 && alpha0 >= 1)
533   {
534     /* 8 bit */
535     bpp16 = FALSE;
536     lutmax = LUTMAX8;
537   }
538   else { 
539     fprintf(stderr,"Got alpha = %d\n",alpha0+1);
540     error("Bad value for alpha. Sorry...\n");
541   }
542
543
544   check_compatibility(head_frame,head_scan[0],0);
545
546   for (i=0;i<components;i++) {
547     samplingx[i]=head_frame->samplingx[i];
548     samplingy[i]=head_frame->samplingy[i];
549     if ((!multi) && ((samplingx[i]!=1) || (samplingy[i]!=1)) && (components>1))
550     {
551       fprintf(stderr,"\nERROR: Cannot use -P (PPM output) with subsampled compressed components\n");
552       exit(10);
553     }
554   }
555
556   if ((!multi) && (color_mode==PLANE_INT))
557     {
558     if (components>1) {
559       fprintf(stderr,"\nERROR: Cannot use -P (PPM output) with plane intereleaved mode\n");
560       exit(10);
561       }
562     }
563   else multi=1;
564
565   if ((multi) && (color_mode==PIXEL_INT)) {
566     multi = 0;   /* equivalent to specifying -P flag */
567   }
568
569   if ((out_files>1) && (color_mode==PIXEL_INT)) {
570     fprintf(stderr,"ERROR: Pixel interleaved mode uses only 1 output file\n");
571     exit(10);
572   }
573
574   if ((multi) && (out_files) && (out_files!=components)) {
575     fprintf(stderr,"ERROR: Number of files, %d, for output must be equal to number of image components, %d\n",out_files,components);
576     exit(10);
577   }
578
579   /* Compute the image size for the different components */
580   if (components==1) {
581     c_columns[0]=columns;
582     c_rows[0]=rows;
583     whose_max_size_rows=0;
584     samplingy[0]=1;
585   }
586   else
587   {
588     max_samp_columns=0;
589     max_samp_rows=0;
590     for(i=0;i<components;i++) {
591       if (samplingx[i]>max_samp_columns) {
592         max_samp_columns=samplingx[i];
593         whose_max_size_columns=i;
594       }
595       if (samplingy[i]>max_samp_rows) {
596         max_samp_rows=samplingy[i];
597         whose_max_size_rows=i;
598       }
599     }
600
601     c_columns[whose_max_size_columns]=columns;  
602     c_rows[whose_max_size_rows]=rows;
603
604     for(i=0;i<components;i++) {
605       if (i!=whose_max_size_columns)
606       {
607         c_columns[i]=c_columns[whose_max_size_columns]*samplingx[i];
608         c_columns[i]/=samplingx[whose_max_size_columns];
609       }
610       if (i!=whose_max_size_rows) {
611         c_rows[i]=c_rows[whose_max_size_rows]*samplingy[i];
612         c_rows[i]/=samplingy[whose_max_size_rows];
613       }
614     }
615   }
616
617
618   /* msgfile seems to start being used here, let's initialize it here */
619   if ( !msgfile ) msgfile = stdout;
620   /* Open out file */
621   if ( outfilename == NULL ) {
622     usage();
623     exit(0);
624   }
625   else {
626     if ( strcmp(outfilename,"-")==0 ) {
627       out = stdout;
628       msgfile = stderr;
629     }
630     else {
631       if (multi==0) {
632         if ( (out=fopen(outfilename,"wb")) == NULL ) {
633           perror(outfilename);
634           exit(10);
635         }
636       }
637       else 
638         for (i=0;i<components;i++)
639           if ( (c_out[i]=fopen(c_outfilename[i],"wb")) == NULL )
640           {
641             perror(c_outfilename[i]);
642             exit(10);
643           }
644       
645     }
646   }
647
648
649   /* check that color mode is valid and pick color mode string */
650   switch ( color_mode ) {
651
652   case PLANE_INT:
653     color_mode_string = plane_int_string;
654     break;
655
656   case LINE_INT:
657     color_mode_string = line_int_string;
658     break;
659   
660     case PIXEL_INT:
661     color_mode_string = pixel_int_string;
662     break;
663
664   default:
665     fprintf(stderr,"ERROR: Invalid color mode %d\n",color_mode);
666     usage();
667     exit(10);
668   }
669
670   if ( verbose ) {
671       fprintf(msgfile,"%s\n",banner);
672   }
673
674   if ( verbose ) {
675     if (!multi) {
676       fprintf(msgfile,"Input  file: %s\nOutput file: %s\n",infilename,outfilename);
677       }
678       else {
679       fprintf(msgfile,"Input  file: %s\nOutput files: ",infilename);
680       for (i=0;i<components;i++)
681         fprintf(msgfile," %s ",c_outfilename[i]);
682       fprintf(msgfile,"\n");
683     }
684   }
685
686 #ifdef FIXALPHA
687   if ( alpha0 != alpha ) {
688       fprintf(stderr, "Sorry, this version has been optimized for alphabet size = %d, got %d\n",alpha,alpha0);
689       exit(10);
690   }
691 #else
692   alpha = alpha0;
693   ceil_half_alpha = (alpha+1)/2;
694 #endif
695
696 #ifdef POW2
697   highmask = -alpha;
698 /* check that alpha is a power of 2 */
699   for ( alpha0=alpha, i=-1; alpha0; alpha0>>=1, i++);
700   if ( alpha != (1<<i) ) {
701     fprintf(stderr, "Sorry, this version has been optimized for alphabet size = power of 2, got %d\n",alpha);
702     exit(10);
703   }
704 #endif  
705
706   if (lossy==TRUE)
707   {
708     /* compute auxiliary parameters for near-lossless (globals) */
709     quant = 2*NEAR+1;
710     qbeta = (alpha + 2*NEAR + quant-1 )/quant;
711     beta = quant*qbeta;
712     ceil_half_qbeta = (qbeta+1)/2;
713     negNEAR = -NEAR;
714     alpha1eps = alpha-1+NEAR;
715     fprintf(msgfile,"Near-lossless mode: NEAR = %d  beta = %d  qbeta = %d\n",NEAR,beta,qbeta);
716   }
717
718   /* compute bits per sample for input symbols */
719   for ( bpp=1; (1L<<bpp)<alpha; bpp++ );
720
721   /* compute bits per sample for unencoded prediction errors */
722   if (lossy==TRUE)
723     for ( qbpp=1; (1L<<qbpp)<qbeta; qbpp++ );
724   else
725     qbpp = bpp;
726
727   if ( bpp < 2 ) bpp = 2;
728
729   /* limit for unary part of Golomb code */
730   if ( bpp < 8 )
731       limit = 2*(bpp + 8) - qbpp -1;
732   else
733       limit = 4*bpp - qbpp - 1;   
734
735   /* print out parameters */
736   if ( verbose ) {
737       if (!multi)
738     fprintf(msgfile,"Image: cols=%d rows=%d alpha=%d comp=%d mode=%d (%s)\nParameters: Ta=%d Tb=%d Tc=%d RESET=%d limit=%d",
739        columns, rows, alpha0, components, 
740        color_mode, color_mode_string,
741        T1, T2, T3, RESET,limit);
742       else {
743       fprintf(msgfile,"Image: cols=");
744       for (i=0;i<components;i++)
745         fprintf(msgfile," %d",c_columns[i]);
746       fprintf(msgfile," rows=");
747       for (i=0;i<components;i++)
748         fprintf(msgfile," %d",c_rows[i]);
749       fprintf(msgfile," alpha=%d comp=%d mode=%d (%s)\nParameters: Ta=%d Tb=%d Tc=%d RESET=%d limit=%d",
750          alpha0, components, 
751         color_mode, color_mode_string,
752         T1, T2, T3,RESET,limit);
753     }
754   }
755
756   if ( verbose )
757       fprintf(msgfile,"\n");
758
759
760   /* Write out the image header for PGM or PPM files */
761   /* Must look at if there are Mapping Tables used */
762
763   /* No Mapping Tables used */
764   if (!head_scan[0]->need_table)
765   {
766     if (!multi) {
767       if (components==1) fputs("P5\n", out);
768       else if (components==3) fputs("P6\n", out);  
769       else if (components==4) fputs("P7\n", out);
770       else fprintf(out,"P%d\n",10+components);
771          
772       fprintf(out,"%d %d\n", columns, rows);
773       fprintf(out,"%d\n", alpha - 1);
774     }
775     else
776       for (i=0;i<components;i++) {
777         fputs("P5\n", c_out[i]);
778         fprintf(c_out[i],"%d %d\n", c_columns[i], c_rows[i]);
779         fprintf(c_out[i],"%d\n", alpha - 1);
780       }
781   }
782
783   /* Mapping Tables used */
784   else
785   {
786     /* only 8 bit indexes supported for mapping tables */
787     if (bpp16==TRUE)
788     {
789       fprintf(stderr, "Sorry, mapping tables are only supported for 8 bpp images in this implementation.\n");
790       exit(0);
791     }
792
793     /* Mapping Table elements are 1 or 2 bytes */
794     if (head_scan[0]->Wt==1 || head_scan[0]->Wt==2)
795     {
796       int alpha_temp;
797       if (head_scan[0]->Wt==1)
798         alpha_temp = alpha;
799       else
800         alpha_temp = alpha*alpha;
801
802       if (!multi) 
803       {
804         if (components==1) fputs("P5\n", out);
805         else if (components==3) fputs("P6\n", out);  
806         else if (components==4) fputs("P7\n", out);
807         else fprintf(out,"P%d\n",10+components);
808          
809         fprintf(out,"%d %d\n", columns, rows);
810         fprintf(out,"%d\n", alpha_temp - 1);
811       }
812       else
813         for (i=0;i<components;i++) 
814         {
815           fputs("P5\n", c_out[i]);
816           fprintf(c_out[i],"%d %d\n", c_columns[i], c_rows[i]);
817           fprintf(c_out[i],"%d\n", alpha_temp - 1);
818         }
819     }
820     
821     /* Mapping Table elements are 3 bytes */
822     else if (head_scan[0]->Wt==3)
823     {
824       if (!multi) 
825       {
826         if (components==1) fputs("P6\n", out);
827         else
828         {
829           fprintf(stderr,"Error : Cannot have a multi-component image and a mapping table with 3 bytes per element.\n");
830           exit(0);
831         }
832
833         fprintf(out,"%d %d\n", columns, rows);
834         fprintf(out,"%d\n", alpha - 1);
835       }
836       else
837         for (i=0;i<components;i++) 
838         {
839           fputs("P6\n", c_out[i]);
840           fprintf(c_out[i],"%d %d\n", c_columns[i], c_rows[i]);
841           fprintf(c_out[i],"%d\n", alpha - 1);
842         }
843     }
844
845     /* Mapping Table elements aren't 1 to 3 bytes */
846     else
847     {
848       fprintf(stderr, "Sorry, mapping tables elements can only be 1 to 3 bytes in this implementation.\n");
849       exit(0);
850     }
851   }
852     
853
854   /* Allocate memory pools. */
855   initbuffers(multi, components);
856
857
858   /* return size of the header, in bytes */
859   return pos;
860
861 }
862
863
864
865
866
867 /* Main loop for decoding files */
868
869 int main (int argc, char *argv[]) {
870   int n,n_c,n_r,my_i,n_s,mk,seek_return;
871   int found_EOF = 0;
872   double t0, t1; /*, get_utime();*/
873   long pos0, pos1,    
874     tot_in = 0,
875     tot_out = 0;
876   pixel *local_scanl0,*local_scanl1,*local_pscanline,*local_cscanline;
877   int MCUs_counted;
878   
879   
880   /* Parse the parameters, initialize */
881   /* Not yet fully implemented */
882   bufiinit(NULL);
883   pos0 = initialize(argc, argv); 
884
885
886   /* start timer (must be AFTER initialize()) */
887   t0 = get_utime();
888
889
890   /* Initialize the scanline buffers */
891   if (!multi)
892     for (n = 0; n <= (columns + 1); ++n)
893       pscanline[n] = 0;       
894   else
895     for (n_c=0;n_c<components;n_c++)
896       for (n = 0; n <= (c_columns[n_c] + 1); ++n)
897         c_pscanline[n_c][n] = 0;       
898
899   if ((components>1) && (multi==0))
900   {
901     /* OUTPUT PPM file, allocate auxiliary buffers */
902     local_scanl0 = (pixel *)safecalloc(columns+LEFTMARGIN+RIGHTMARGIN,sizeof (pixel) );
903     local_scanl1 = (pixel *)safecalloc(columns+LEFTMARGIN+RIGHTMARGIN,sizeof (pixel) );
904
905     local_pscanline = local_scanl0 + LEFTMARGIN-1;
906     local_cscanline = local_scanl1 + LEFTMARGIN-1;
907   }
908
909
910   for (n_s=0;n_s<number_of_scans;n_s++)
911   {
912     /* Repeat prediction/quantization/statistics scanline by scanline,
913        for each scan. */
914
915     /* Reset Restart Markers for every scan */
916     MCUs_counted = 0;
917     
918     /* This implementation supports parameters in 1st scan */
919     if (n_s==0)
920     {
921       /* Prepare the quantization LUTs */
922       prepareLUTs();
923
924       if (lossy==TRUE)
925         /* prepare div/mul tables for near-lossless quantization */
926         prepare_qtables(alpha,NEAR);
927
928     }
929     else
930     {  /* Read further scan headers */
931       seek_return=seek_marker(in,&mk);
932       if (seek_return == EOF)
933       {
934         fprintf(stderr,"*** Premature End of File seeking SOS marker\n");
935         exit(10);
936       }
937       if ( seek_return > 2 )
938       {
939         fprintf(msgfile,"*** WARNING: %d extra bytes between end of scan and next marker.\n",seek_return-2);
940         fprintf(msgfile,"***          Added to marker segment count.\n");
941       }
942       pos0 +=seek_return;
943       if (mk != SOS)
944       {
945         fprintf(stderr,"Expecting SOS (%04x), got %04x\n",SOS,mk);
946         exit(10);
947       }
948       seek_return = read_jpegls_scan(in,head_scan[n_s]); /* Read the scan header*/
949       if (seek_return == EOF)
950       {
951         fprintf(stderr,"*** Premature End of File reading scan marker segment\n");
952         exit(10);
953       }
954       pos0+=seek_return;
955       if (head_scan[n_s]->shift!=0)
956       {
957         fprintf(stderr,"Got shift = %d != 0 : not implemented.\n",head_scan[n_s]->shift);
958         exit(10);
959       }
960       if (head_scan[n_s]->NEAR != NEAR)
961       {
962         fprintf(stderr,"Got NEAR=%d after NEAR=%d: cannot change parameters between scans in this implementation\n",head_scan[n_s]->NEAR,NEAR);
963         exit(10);
964       }
965       if ((head_scan[n_s]->color_mode != PLANE_INT) || (head_scan[n_s]->comp != 1) ||
966         (head_scan[n_s]->comp_ids[0] != n_s+1))
967       {
968         fprintf(stderr,"This implementation supports multiple scans only in PLANE INTERLEAVED mode.\n");
969         exit(10);
970       }
971     }
972
973     /* Initializations for each scan */
974     bitiinit();
975
976     /* Start from 1st image row */
977     n=0;
978
979         /* Initialize stats arrays */
980     if (lossy==TRUE)
981       init_stats(qbeta);
982     else
983       init_stats(alpha);
984
985     /* Initialize run processing */
986     init_process_run(MAXRUN);
987
988     if (color_mode==LINE_INT) {    /* line int. */
989       if (!multi) {
990 /***********************************************************************/
991 /*           Line interleaved mode with single file received           */
992 /***********************************************************************/
993
994         if (lossy==FALSE)
995           
996           /* LOSSLESS MODE */
997           while (++n <= rows)
998           {
999             /* 'extend' the edges */
1000             for (n_c=0;n_c<components;n_c++)
1001               cscanline[-components+n_c]=cscanline[n_c]=pscanline[components+n_c];
1002
1003             for (n_c=0;n_c<components;n_c++)
1004             {
1005               if (components>1)
1006                 for (my_i=0;my_i<columns+LEFTMARGIN+RIGHTMARGIN;my_i++)
1007                 {
1008                   local_cscanline[-1+my_i]=cscanline[-components+my_i*components+n_c];
1009                   local_pscanline[-1+my_i]=pscanline[-components+my_i*components+n_c];
1010                 }
1011               else 
1012               {
1013                 local_cscanline=cscanline;
1014                 local_pscanline=pscanline;
1015               }
1016
1017               if ( lossless_undoscanline(local_pscanline, local_cscanline, columns, n_c ) != 0 )
1018               {
1019                 fprintf(stderr,"*** Premature EOF: expected %d rows, got %d\n",rows, n-1);
1020                 found_EOF = 1;
1021                 break;
1022               }
1023
1024               if (components>1)
1025                 for (my_i=0;my_i<columns+LEFTMARGIN+RIGHTMARGIN;my_i++)
1026                   cscanline[-components+my_i*components+n_c]=local_cscanline[-1+my_i];
1027             }
1028
1029             write_one_line(cscanline + components, components*columns, out);
1030
1031             tot_out += components*columns;
1032
1033             /* extend the edges */
1034             for (n_c=0;n_c<components;n_c++)
1035               cscanline[components*(columns+1)+n_c] = cscanline[components*columns+n_c];
1036
1037             /* make the current scanline the previous one */
1038             swaplines();
1039
1040             /* Take out the Restart Markers */
1041             if (got_restart)
1042             {
1043               /* Look for restart markers only after a restart interval */
1044               if ((MCUs_counted % restart_interval) == 0)
1045               {
1046                 bitiflush();
1047                 read_n_bytes(in, 2);  /* read the RST marker */
1048                 bitiinit();
1049               }
1050               MCUs_counted++;
1051               
1052             }
1053
1054           }  /* End of while loop for each file line */
1055
1056         else
1057
1058           /* LOSSY MODE */
1059           while (++n <= rows)
1060           {
1061             /* 'extend' the edges */
1062             for (n_c=0;n_c<components;n_c++)
1063               cscanline[-components+n_c]=cscanline[n_c]=pscanline[components+n_c];
1064
1065             for (n_c=0;n_c<components;n_c++)
1066             {
1067               if (components>1)
1068                 for (my_i=0;my_i<columns+LEFTMARGIN+RIGHTMARGIN;my_i++)
1069                 {
1070                   local_cscanline[-1+my_i]=cscanline[-components+my_i*components+n_c];
1071                   local_pscanline[-1+my_i]=pscanline[-components+my_i*components+n_c];
1072                 }
1073               else 
1074               {
1075                 local_cscanline=cscanline;
1076                 local_pscanline=pscanline;
1077               }
1078
1079               if ( lossy_undoscanline(local_pscanline, local_cscanline, columns, n_c ) != 0 )
1080               {
1081                 fprintf(stderr,"*** Premature EOF: expected %d rows, got %d\n",rows, n-1);
1082                 found_EOF = 1;
1083                 break;
1084               }
1085
1086               if (components>1)
1087                 for (my_i=0;my_i<columns+LEFTMARGIN+RIGHTMARGIN;my_i++)
1088                   cscanline[-components+my_i*components+n_c]=local_cscanline[-1+my_i];
1089             }
1090
1091             write_one_line(cscanline + components, components*columns, out);
1092
1093             tot_out += components*columns;
1094
1095             /* extend the edges */
1096             for (n_c=0;n_c<components;n_c++)
1097               cscanline[components*(columns+1)+n_c] = cscanline[components*columns+n_c];
1098
1099             /* make the current scanline the previous one */
1100             swaplines();
1101
1102             /* Take out the Restart Markers */
1103             if (got_restart)
1104             {
1105               /* Look for restart markers only after a restart interval */
1106               if ((MCUs_counted % restart_interval) == 0)
1107               {
1108                 bitiflush();
1109                 read_n_bytes(in, 2);  /* read the RST marker */
1110                 bitiinit();
1111               }
1112               MCUs_counted++;
1113               
1114             }
1115
1116           }  /* End of while loop for each file line */
1117
1118       }
1119       else
1120       {    /* Multiple files */
1121       /* color_mode==LINE_INT and multi==1 */
1122 /***********************************************************************/
1123 /*           Line interleaved mode with multiple files received        */
1124 /***********************************************************************/
1125
1126         n++;
1127
1128         if (lossy==FALSE)
1129
1130           /* LOSSLESS MODE */
1131           while (n <= c_rows[whose_max_size_rows])
1132           {
1133             for (n_c=0;n_c<components;n_c++)
1134             {
1135               for (n_r=0;n_r<samplingy[n_c];n_r++)
1136               {
1137
1138                 /* 'extend' the edges */
1139                 c_cscanline[n_c][-1]=c_cscanline[n_c][0]=c_pscanline[n_c][1];
1140
1141                 if ( lossless_undoscanline(c_pscanline[n_c], c_cscanline[n_c], c_columns[n_c], n_c ) != 0 )
1142                 {
1143                   fprintf(stderr,"*** Premature EOF: expected %d rows, got %d\n",rows, n-1);
1144                   found_EOF = 1;
1145                   break;
1146                 }
1147
1148                 write_one_line(c_cscanline[n_c] + 1, c_columns[n_c], c_out[n_c]);
1149
1150                 tot_out += c_columns[n_c];
1151
1152                 /* extend the edges */
1153                 c_cscanline[n_c][c_columns[n_c]+1] = c_cscanline[n_c][c_columns[n_c]];
1154
1155                 /* make the current scanline the previous one */
1156                 c_swaplines(n_c);
1157               }
1158             }  /* End of for loop for each component */
1159
1160             n+=samplingy[whose_max_size_rows];
1161
1162             /* Take out the Restart Markers */
1163             if (got_restart)
1164             {
1165               /* Look for restart markers only after a restart interval */
1166               if ((MCUs_counted % restart_interval) == 0)
1167               {
1168                 bitiflush();
1169                 read_n_bytes(in, 2);  /* read the RST marker */
1170                 bitiinit();
1171               }
1172               MCUs_counted++;
1173               
1174             }
1175
1176           }  /* End of while loop for each line */
1177
1178         else
1179
1180           /* LOSSY MODE */
1181           while (n <= c_rows[whose_max_size_rows])
1182           {
1183             for (n_c=0;n_c<components;n_c++)
1184             {
1185               for (n_r=0;n_r<samplingy[n_c];n_r++)
1186               {
1187
1188                 /* 'extend' the edges */
1189                 c_cscanline[n_c][-1]=c_cscanline[n_c][0]=c_pscanline[n_c][1];
1190
1191                 if ( lossy_undoscanline(c_pscanline[n_c], c_cscanline[n_c], c_columns[n_c], n_c ) != 0 )
1192                 {
1193                   fprintf(stderr,"*** Premature EOF: expected %d rows, got %d\n",rows, n-1);
1194                   found_EOF = 1;
1195                   break;
1196                 }
1197
1198                 write_one_line(c_cscanline[n_c] + 1, c_columns[n_c], c_out[n_c]);
1199
1200                 tot_out += c_columns[n_c];
1201
1202                 /* extend the edges */
1203                 c_cscanline[n_c][c_columns[n_c]+1] = c_cscanline[n_c][c_columns[n_c]];
1204
1205                 /* make the current scanline the previous one */
1206                 c_swaplines(n_c);
1207               }
1208             }  /* End of for loop for each component */
1209
1210             n+=samplingy[whose_max_size_rows];
1211
1212             /* Take out the Restart Markers */
1213             if (got_restart)
1214             {
1215               /* Look for restart markers only after a restart interval */
1216               if ((MCUs_counted % restart_interval) == 0)
1217               {
1218                 bitiflush();
1219                 read_n_bytes(in, 2);  /* read the RST marker */
1220                 bitiinit();
1221               }
1222               MCUs_counted++;
1223               
1224             }
1225
1226           }  /* End of while loop for each line */
1227
1228
1229       }    /* Closes the else, LINE_INT and multi=1 */
1230
1231     }    /* End of part for LINE_INT */
1232
1233     else {    /* Non LINE_INT mode */
1234       if (color_mode==PIXEL_INT) {
1235 /***********************************************************************/
1236 /*           Pixel interleaved mode with single file received          */
1237 /***********************************************************************/
1238
1239         if (lossy==FALSE)
1240         
1241           /* LOSSLESS MODE */
1242           while (++n <= rows)
1243           {
1244             /* 'extend' the edges */
1245             for (n_c=0;n_c<components;n_c++)
1246               cscanline[-components+n_c]=cscanline[n_c]=pscanline[components+n_c];
1247
1248             if ( lossless_undoscanline_pixel(pscanline, cscanline, components*columns) != 0 )
1249             {
1250               fprintf(stderr,"*** Premature EOF: expected %d rows, got %d\n",rows,n-1);
1251               found_EOF = 1;
1252               break;
1253             }
1254
1255             write_one_line(cscanline+components, components*columns, out);
1256     
1257             tot_out += components*columns;
1258
1259             /* extend the edges */
1260             for (n_c=0;n_c<components;n_c++)
1261               cscanline[components*(columns+1)+n_c] = cscanline[components*columns+n_c];
1262
1263             /* make the current scanline the previous one */
1264             swaplines();
1265
1266             /* Take out the Restart Markers */
1267             if (got_restart)
1268             {
1269               /* Look for restart markers only after a restart interval */
1270               if ((MCUs_counted % restart_interval) == 0)
1271               {
1272                 bitiflush();
1273                 read_n_bytes(in, 2);  /* read the RST marker */
1274                 bitiinit();
1275               }
1276               MCUs_counted++;
1277               
1278             }
1279
1280           }  /* End of line loop for PIXEL_INT */
1281
1282
1283         else
1284
1285           /* LOSSY MODE */
1286           while (++n <= rows)
1287           {
1288             /* 'extend' the edges */
1289             for (n_c=0;n_c<components;n_c++)
1290               cscanline[-components+n_c]=cscanline[n_c]=pscanline[components+n_c];
1291
1292             if ( lossy_undoscanline_pixel(pscanline, cscanline, components*columns) != 0 )
1293             {
1294               fprintf(stderr,"*** Premature EOF: expected %d rows, got %d\n",rows,n-1);
1295               found_EOF = 1;
1296               break;
1297             }
1298
1299             write_one_line(cscanline+components, components*columns, out);
1300
1301             tot_out += components*columns;
1302
1303             /* extend the edges */
1304             for (n_c=0;n_c<components;n_c++)
1305               cscanline[components*(columns+1)+n_c] = cscanline[components*columns+n_c];
1306
1307             /* make the current scanline the previous one */
1308             swaplines();
1309
1310             /* Take out the Restart Markers */
1311             if (got_restart)
1312             {
1313               /* Look for restart markers only after a restart interval */
1314               if ((MCUs_counted % restart_interval) == 0)
1315               {
1316                 bitiflush();
1317                 read_n_bytes(in, 2);  /* read the RST marker */
1318                 bitiinit();
1319               }
1320               MCUs_counted++;
1321               
1322             }
1323
1324           }  /* End of line loop for PIXEL_INT */
1325
1326       }
1327       else {
1328 /***********************************************************************/
1329 /*           Plane interleaved mode                */
1330 /***********************************************************************/
1331
1332         if (lossy==FALSE)
1333         
1334           /* LOSSLESS MODE */
1335           while (++n <= c_rows[n_s])
1336           {
1337             /* 'extend' the edges */
1338             c_cscanline[n_s][-1]=c_cscanline[n_s][0]=c_pscanline[n_s][1];
1339
1340             if (lossless_undoscanline(c_pscanline[n_s], c_cscanline[n_s], c_columns[n_s], n_s ) != 0 )
1341             {
1342               fprintf(stderr,"*** Premature EOF: expected %d rows, got %d\n",rows, n-1);
1343               found_EOF = 1;
1344               break;
1345             }
1346
1347             write_one_line(c_cscanline[n_s]+1, c_columns[n_s], c_out[n_s]);
1348
1349             tot_out += c_columns[n_s];
1350
1351             /* extend the edges */
1352             c_cscanline[n_s][c_columns[n_s]+1] = c_cscanline[n_s][c_columns[n_s]];
1353
1354             /* make the current scanline the previous one */
1355             c_swaplines(n_s);
1356
1357             /* Take out the Restart Markers */
1358             if (got_restart)
1359             {
1360               /* Look for restart markers only after a restart interval */
1361               if ((MCUs_counted % restart_interval) == 0)
1362               {
1363                 bitiflush();
1364                 read_n_bytes(in, 2);  /* read the RST marker */
1365                 bitiinit();
1366               }
1367               MCUs_counted++;
1368               
1369             }
1370
1371           }  /* End of line loop in PLANE_INT */
1372         
1373         else
1374
1375           /* LOSSY MODE */
1376           while (++n <= c_rows[n_s])
1377           {
1378             /* 'extend' the edges */
1379             c_cscanline[n_s][-1]=c_cscanline[n_s][0]=c_pscanline[n_s][1];
1380
1381             if (lossy_undoscanline(c_pscanline[n_s], c_cscanline[n_s], c_columns[n_s], n_s ) != 0 )
1382             {
1383               fprintf(stderr,"*** Premature EOF: expected %d rows, got %d\n",rows, n-1);
1384               found_EOF = 1;
1385               break;
1386             }
1387
1388             write_one_line(c_cscanline[n_s]+1, c_columns[n_s], c_out[n_s]);
1389
1390             tot_out += c_columns[n_s];
1391
1392             /* extend the edges */
1393             c_cscanline[n_s][c_columns[n_s]+1] = c_cscanline[n_s][c_columns[n_s]];
1394
1395             /* make the current scanline the previous one */
1396             c_swaplines(n_s);
1397
1398             /* Take out the Restart Markers */
1399             if (got_restart)
1400             {
1401               /* Look for restart markers only after a restart interval */
1402               if ((MCUs_counted % restart_interval) == 0)
1403               {
1404                 bitiflush();
1405                 read_n_bytes(in, 2);  /* read the RST marker */
1406                 bitiinit();
1407               }
1408               MCUs_counted++;
1409               
1410             }
1411
1412           }  /* End of line loop in PLANE_INT */
1413
1414       }  /* End of each component for PLANE_INT */
1415
1416     }  /* End of non LINE_INT */
1417
1418     bitiflush();
1419
1420   } /* End of loop for scans */
1421
1422
1423   mk = 0;
1424
1425   /* Read EOI */
1426   seek_return=seek_marker(in,&mk);
1427   if (seek_return==EOF)
1428   {
1429     fprintf(stderr,"Did not get EOI at end of compressed image\n");
1430     exit(10);
1431   }
1432   if ( seek_return > 2 )
1433   {
1434       fprintf(msgfile,"*** WARNING: %d extra bytes between end of scan and next marker.\n",seek_return-2);
1435       fprintf(msgfile,"***          Added to marker segment count.\n");
1436   }
1437
1438   pos0 += seek_return;
1439   if (mk != EOI)
1440   {
1441     fprintf(stderr,"In this implementation last marker must be EOI\n");
1442     exit(10);
1443   }
1444
1445   if (head_scan[0]->need_table)
1446     fprintf(msgfile,"A mapping table was used which had %i entries of %i bytes each.\n",head_scan[0]->MAXTAB, head_scan[0]->Wt);
1447
1448   if (got_restart)
1449     fprintf(msgfile,"Restart markers were found with a restart interval of %i.\n",restart_interval);
1450
1451   if ( verbose )
1452     fprintf(msgfile,"Marker segment bytes: %ld\n",pos0);
1453
1454   /* position in input file */
1455   pos1 = ftell(in);
1456   /* tot_in = 8*(pos1-pos0); */
1457
1458   /* size of compressed file read (bits), incl. headers. */
1459   tot_in = 8*pos1;
1460
1461   /* Close down */
1462   close_process_run();
1463   closebuffers(multi);
1464
1465
1466   t1 = get_utime();
1467   fprintf(msgfile,"Total bits  in: %ld  Symbols out: %ld  %5.3lf bps\n",
1468            tot_in,tot_out,tot_in/(double)tot_out);
1469   fprintf(msgfile,"Time = %1.3lf secs : %1.0lf KSymbols/sec\n",t1-t0,
1470           (tot_out)/(1024*(t1-t0)));
1471
1472   if ( found_EOF )
1473     exit(0);
1474   else
1475     return 1;
1476 }
1477
1478
1479
1480
1481 void usage()
1482 {
1483   fprintf(stderr,"Usage: %s [flags] [infile] [outfile1 [outfile2, ...]]\n\
1484 DEFAULTS:\n\
1485 infile   = %s.\n\
1486 outfile1 = %s for color image in a single (PPM) output file.\n\
1487 outfile1 = %s for monochrome image in a single (PGM) output file.\n\
1488 outfile[1,2,...] = %s for multiple (PGM) output files \n\
1489      in plane or line interleaved modes.\n",
1490     "locod", "specified JLS file", OUTFILE ".out", 
1491     OUTFILE "1.out",
1492     OUTFILE "[1,2,...].out");
1493 fprintf(stderr,"FLAGS:\n\
1494 outfile2, ... : Multiple output specification for plane or line int. mode.\n\
1495 -i<infile>    : Alternate input specification, use -i- for stdin.\n\
1496 -o<outfile>   : Alternate output specification, use -o- for stdout.\n\
1497 -P            : Generate single (.ppm) output file for sample/line int. mode.\n\
1498 ");
1499     fprintf(stderr,"\
1500 -h            : Print this help.\n\
1501 *** No spaces allowed between a flag and its argument.\n\
1502 ");
1503   
1504 }
1505
1506
1507 void bad_flag(char *s)
1508 {
1509     fprintf(stderr,"Bad flag %s\n",s);
1510     usage();
1511     exit(10);
1512 }
1513