]> Creatis software - gdcm.git/blob - src/gdcmjpegls/Decoder/decoder.c
COMP: Remove another warning on icc81
[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
122
123
124
125
126 /* Write one row of pixel values */
127 inline void write_one_line(pixel* line, int cols, FILE* outfile)
128 {
129   int i, index;
130   unsigned int* maptable;
131       
132   /* No mapping tables used */
133   if(!(head_scan[0]->need_table))
134     if (bpp16==FALSE)
135     {
136       unsigned char* line8;
137       line8 = (unsigned char*)safealloc(cols);
138   
139       for (i=0; i< cols; i++)
140         *(line8+i)=(unsigned char)ENDIAN8(*(line+i));
141     
142       fwrite(line8, sizeof(unsigned char), cols, outfile);
143
144       free(line8);
145     } else {
146       fwrite(line, sizeof(short), cols, outfile);
147     }
148
149   /* Mapping tables used */
150   else
151   {
152     if (bpp16==FALSE)
153     {
154       /* Write one byte per table entry */
155       if (head_scan[0]->Wt == 1)
156       {
157         unsigned char* line8;
158         line8 = (unsigned char*)safealloc(cols);  /* If don't have 2, it mallocs over the table? */
159
160         maptable = head_scan[0]->TABLE[head_scan[0]->TID];
161
162         for (i=0; i<cols; i++)
163         {
164           index = *(line+i);
165           *(line8+i) = ENDIAN8(maptable[index]);
166         }
167
168         fwrite(line8, sizeof(unsigned char), cols, outfile);
169
170         free(line8);
171       }
172       /* Write two bytes per table entry */
173       else if (head_scan[0]->Wt == 2)
174       {
175         unsigned short* line16;
176         line16 = (unsigned short*)safealloc(cols*2);
177
178         maptable = head_scan[0]->TABLE[head_scan[0]->TID];
179
180         for (i=0; i<cols; i++)
181         {
182           index = *(line+i);
183           *(line16+i) = (unsigned short) maptable[index];
184         }
185
186         fwrite(line16, sizeof(short), cols, outfile);
187
188         free(line16);
189       }
190       /* Write three bytes per table entry */
191       else if (head_scan[0]->Wt == 3)
192       {
193         unsigned char* line8_3;
194         line8_3 = (unsigned char*)safealloc(cols*3);
195
196         maptable = head_scan[0]->TABLE[head_scan[0]->TID];
197
198         for (i=0; i<cols; i++)
199         {
200           index = *(line+i);
201           *(line8_3 + (i*3)) =  (unsigned char) (maptable[index] >> 16);
202           *(line8_3 + (i*3) + 1) = (unsigned char) (maptable[index] >> 8);
203           *(line8_3 + (i*3) + 2) = (unsigned char) (maptable[index]);
204         }
205
206         fwrite(line8_3, sizeof(char), cols*3, outfile);
207
208         free(line8_3);
209       }
210
211           
212     /* Can't do 16 bit index values */
213     }
214     else
215     {
216       fprintf(stderr, "Sorry, mapping tables are only supported for 8 bpp images in this implementation.\n");
217       exit(0);
218     }
219   }
220
221
222 }
223
224
225
226
227
228 void initbuffers(int multi, int comp)
229 {
230
231   int  i;
232
233   if (multi)     /* Output to several files */
234
235     for (i=0;i<comp;i++) {
236
237       c_pscanl0[i] = (pixel *)safecalloc((c_columns[i]+LEFTMARGIN+RIGHTMARGIN), sizeof(pixel) );
238       c_cscanl0[i] = (pixel *)safecalloc((c_columns[i]+LEFTMARGIN+RIGHTMARGIN), sizeof(pixel) );
239
240       /* Adjust scan line pointers taking into account the margins,
241          and also the fact that indexing for scan lines starts from 1
242        */
243       c_pscanline[i] = c_pscanl0[i] + (LEFTMARGIN-1);
244       c_cscanline[i] = c_cscanl0[i] + (LEFTMARGIN-1);
245     }
246
247   else {      /* Output to a single file */
248
249     pscanl0 = (pixel *)safecalloc(components*(columns+LEFTMARGIN+RIGHTMARGIN), sizeof(pixel) );
250     cscanl0 = (pixel *)safecalloc(components*(columns+LEFTMARGIN+RIGHTMARGIN), sizeof(pixel) );
251
252     /* Adjust scan line pointers taking into account the margins,
253        and also the fact that indexing for scan lines starts from 1
254        (this will probably have to be changed in the future) 
255      */
256     pscanline = pscanl0 + components*(LEFTMARGIN-1);
257     cscanline = cscanl0 + components*(LEFTMARGIN-1);
258   }
259
260     createzeroLUT();
261
262 }
263
264 void swaplines()
265 {
266   pixel *temp;
267   temp = pscanl0;
268   pscanl0 = cscanl0;
269   cscanl0 = temp;
270   pscanline = pscanl0 + components*(LEFTMARGIN-1);
271   cscanline = cscanl0 + components*(LEFTMARGIN-1);
272 }
273
274 void c_swaplines(int i)
275 {
276   pixel *temp;
277   temp = c_pscanl0[i];
278   c_pscanl0[i] = c_cscanl0[i];
279   c_cscanl0[i] = temp;
280   c_pscanline[i] = c_pscanl0[i] + (LEFTMARGIN-1);
281   c_cscanline[i] = c_cscanl0[i] + (LEFTMARGIN-1);
282 }
283
284 void closebuffers(int multi)
285 {
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 /* command line argument parsing */
302 int initialize(int argc, char *argv[])
303 {
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]=(char*)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   local_cscanline = local_pscanline = NULL;
879   
880   
881   /* Parse the parameters, initialize */
882   /* Not yet fully implemented */
883   bufiinit(NULL);
884   pos0 = initialize(argc, argv); 
885
886
887   /* start timer (must be AFTER initialize()) */
888   t0 = get_utime();
889
890
891   /* Initialize the scanline buffers */
892   if (!multi)
893     for (n = 0; n <= (columns + 1); ++n)
894       pscanline[n] = 0;       
895   else
896     for (n_c=0;n_c<components;n_c++)
897       for (n = 0; n <= (c_columns[n_c] + 1); ++n)
898         c_pscanline[n_c][n] = 0;       
899
900   if ((components>1) && (multi==0))
901   {
902     /* OUTPUT PPM file, allocate auxiliary buffers */
903     local_scanl0 = (pixel *)safecalloc(columns+LEFTMARGIN+RIGHTMARGIN,sizeof (pixel) );
904     local_scanl1 = (pixel *)safecalloc(columns+LEFTMARGIN+RIGHTMARGIN,sizeof (pixel) );
905
906     local_pscanline = local_scanl0 + LEFTMARGIN-1;
907     local_cscanline = local_scanl1 + LEFTMARGIN-1;
908   }
909
910
911   for (n_s=0;n_s<number_of_scans;n_s++)
912   {
913     /* Repeat prediction/quantization/statistics scanline by scanline,
914        for each scan. */
915
916     /* Reset Restart Markers for every scan */
917     MCUs_counted = 0;
918     
919     /* This implementation supports parameters in 1st scan */
920     if (n_s==0)
921     {
922       /* Prepare the quantization LUTs */
923       prepareLUTs();
924
925       if (lossy==TRUE)
926         /* prepare div/mul tables for near-lossless quantization */
927         prepare_qtables(alpha,NEAR);
928
929     }
930     else
931     {  /* Read further scan headers */
932       seek_return=seek_marker(in,&mk);
933       if (seek_return == EOF)
934       {
935         fprintf(stderr,"*** Premature End of File seeking SOS marker\n");
936         exit(10);
937       }
938       if ( seek_return > 2 )
939       {
940         fprintf(msgfile,"*** WARNING: %d extra bytes between end of scan and next marker.\n",seek_return-2);
941         fprintf(msgfile,"***          Added to marker segment count.\n");
942       }
943       pos0 +=seek_return;
944       if (mk != SOS)
945       {
946         fprintf(stderr,"Expecting SOS (%04x), got %04x\n",SOS,mk);
947         exit(10);
948       }
949       seek_return = read_jpegls_scan(in,head_scan[n_s]); /* Read the scan header*/
950       if (seek_return == EOF)
951       {
952         fprintf(stderr,"*** Premature End of File reading scan marker segment\n");
953         exit(10);
954       }
955       pos0+=seek_return;
956       if (head_scan[n_s]->shift!=0)
957       {
958         fprintf(stderr,"Got shift = %d != 0 : not implemented.\n",head_scan[n_s]->shift);
959         exit(10);
960       }
961       if (head_scan[n_s]->NEAR != NEAR)
962       {
963         fprintf(stderr,"Got NEAR=%d after NEAR=%d: cannot change parameters between scans in this implementation\n",head_scan[n_s]->NEAR,NEAR);
964         exit(10);
965       }
966       if ((head_scan[n_s]->color_mode != PLANE_INT) || (head_scan[n_s]->comp != 1) ||
967         (head_scan[n_s]->comp_ids[0] != n_s+1))
968       {
969         fprintf(stderr,"This implementation supports multiple scans only in PLANE INTERLEAVED mode.\n");
970         exit(10);
971       }
972     }
973
974     /* Initializations for each scan */
975     bitiinit();
976
977     /* Start from 1st image row */
978     n=0;
979
980         /* Initialize stats arrays */
981     if (lossy==TRUE)
982       init_stats(qbeta);
983     else
984       init_stats(alpha);
985
986     /* Initialize run processing */
987     init_process_run(MAXRUN);
988
989     if (color_mode==LINE_INT) {    /* line int. */
990       if (!multi) {
991 /***********************************************************************/
992 /*           Line interleaved mode with single file received           */
993 /***********************************************************************/
994
995         if (lossy==FALSE)
996           
997           /* LOSSLESS MODE */
998           while (++n <= rows)
999           {
1000             /* 'extend' the edges */
1001             for (n_c=0;n_c<components;n_c++)
1002               cscanline[-components+n_c]=cscanline[n_c]=pscanline[components+n_c];
1003
1004             for (n_c=0;n_c<components;n_c++)
1005             {
1006               if (components>1)
1007                 for (my_i=0;my_i<columns+LEFTMARGIN+RIGHTMARGIN;my_i++)
1008                 {
1009                   local_cscanline[-1+my_i]=cscanline[-components+my_i*components+n_c];
1010                   local_pscanline[-1+my_i]=pscanline[-components+my_i*components+n_c];
1011                 }
1012               else 
1013               {
1014                 local_cscanline=cscanline;
1015                 local_pscanline=pscanline;
1016               }
1017
1018               if ( lossless_undoscanline(local_pscanline, local_cscanline, columns, n_c ) != 0 )
1019               {
1020                 fprintf(stderr,"*** Premature EOF: expected %d rows, got %d\n",rows, n-1);
1021                 found_EOF = 1;
1022                 break;
1023               }
1024
1025               if (components>1)
1026                 for (my_i=0;my_i<columns+LEFTMARGIN+RIGHTMARGIN;my_i++)
1027                   cscanline[-components+my_i*components+n_c]=local_cscanline[-1+my_i];
1028             }
1029
1030             write_one_line(cscanline + components, components*columns, out);
1031
1032             tot_out += components*columns;
1033
1034             /* extend the edges */
1035             for (n_c=0;n_c<components;n_c++)
1036               cscanline[components*(columns+1)+n_c] = cscanline[components*columns+n_c];
1037
1038             /* make the current scanline the previous one */
1039             swaplines();
1040
1041             /* Take out the Restart Markers */
1042             if (got_restart)
1043             {
1044               /* Look for restart markers only after a restart interval */
1045               if ((MCUs_counted % restart_interval) == 0)
1046               {
1047                 bitiflush();
1048                 read_n_bytes(in, 2);  /* read the RST marker */
1049                 bitiinit();
1050               }
1051               MCUs_counted++;
1052               
1053             }
1054
1055           }  /* End of while loop for each file line */
1056
1057         else
1058
1059           /* LOSSY MODE */
1060           while (++n <= rows)
1061           {
1062             /* 'extend' the edges */
1063             for (n_c=0;n_c<components;n_c++)
1064               cscanline[-components+n_c]=cscanline[n_c]=pscanline[components+n_c];
1065
1066             for (n_c=0;n_c<components;n_c++)
1067             {
1068               if (components>1)
1069                 for (my_i=0;my_i<columns+LEFTMARGIN+RIGHTMARGIN;my_i++)
1070                 {
1071                   local_cscanline[-1+my_i]=cscanline[-components+my_i*components+n_c];
1072                   local_pscanline[-1+my_i]=pscanline[-components+my_i*components+n_c];
1073                 }
1074               else 
1075               {
1076                 local_cscanline=cscanline;
1077                 local_pscanline=pscanline;
1078               }
1079
1080               if ( lossy_undoscanline(local_pscanline, local_cscanline, columns, n_c ) != 0 )
1081               {
1082                 fprintf(stderr,"*** Premature EOF: expected %d rows, got %d\n",rows, n-1);
1083                 found_EOF = 1;
1084                 break;
1085               }
1086
1087               if (components>1)
1088                 for (my_i=0;my_i<columns+LEFTMARGIN+RIGHTMARGIN;my_i++)
1089                   cscanline[-components+my_i*components+n_c]=local_cscanline[-1+my_i];
1090             }
1091
1092             write_one_line(cscanline + components, components*columns, out);
1093
1094             tot_out += components*columns;
1095
1096             /* extend the edges */
1097             for (n_c=0;n_c<components;n_c++)
1098               cscanline[components*(columns+1)+n_c] = cscanline[components*columns+n_c];
1099
1100             /* make the current scanline the previous one */
1101             swaplines();
1102
1103             /* Take out the Restart Markers */
1104             if (got_restart)
1105             {
1106               /* Look for restart markers only after a restart interval */
1107               if ((MCUs_counted % restart_interval) == 0)
1108               {
1109                 bitiflush();
1110                 read_n_bytes(in, 2);  /* read the RST marker */
1111                 bitiinit();
1112               }
1113               MCUs_counted++;
1114               
1115             }
1116
1117           }  /* End of while loop for each file line */
1118
1119       }
1120       else
1121       {    /* Multiple files */
1122       /* color_mode==LINE_INT and multi==1 */
1123 /***********************************************************************/
1124 /*           Line interleaved mode with multiple files received        */
1125 /***********************************************************************/
1126
1127         n++;
1128
1129         if (lossy==FALSE)
1130
1131           /* LOSSLESS MODE */
1132           while (n <= c_rows[whose_max_size_rows])
1133           {
1134             for (n_c=0;n_c<components;n_c++)
1135             {
1136               for (n_r=0;n_r<samplingy[n_c];n_r++)
1137               {
1138
1139                 /* 'extend' the edges */
1140                 c_cscanline[n_c][-1]=c_cscanline[n_c][0]=c_pscanline[n_c][1];
1141
1142                 if ( lossless_undoscanline(c_pscanline[n_c], c_cscanline[n_c], c_columns[n_c], n_c ) != 0 )
1143                 {
1144                   fprintf(stderr,"*** Premature EOF: expected %d rows, got %d\n",rows, n-1);
1145                   found_EOF = 1;
1146                   break;
1147                 }
1148
1149                 write_one_line(c_cscanline[n_c] + 1, c_columns[n_c], c_out[n_c]);
1150
1151                 tot_out += c_columns[n_c];
1152
1153                 /* extend the edges */
1154                 c_cscanline[n_c][c_columns[n_c]+1] = c_cscanline[n_c][c_columns[n_c]];
1155
1156                 /* make the current scanline the previous one */
1157                 c_swaplines(n_c);
1158               }
1159             }  /* End of for loop for each component */
1160
1161             n+=samplingy[whose_max_size_rows];
1162
1163             /* Take out the Restart Markers */
1164             if (got_restart)
1165             {
1166               /* Look for restart markers only after a restart interval */
1167               if ((MCUs_counted % restart_interval) == 0)
1168               {
1169                 bitiflush();
1170                 read_n_bytes(in, 2);  /* read the RST marker */
1171                 bitiinit();
1172               }
1173               MCUs_counted++;
1174               
1175             }
1176
1177           }  /* End of while loop for each line */
1178
1179         else
1180
1181           /* LOSSY MODE */
1182           while (n <= c_rows[whose_max_size_rows])
1183           {
1184             for (n_c=0;n_c<components;n_c++)
1185             {
1186               for (n_r=0;n_r<samplingy[n_c];n_r++)
1187               {
1188
1189                 /* 'extend' the edges */
1190                 c_cscanline[n_c][-1]=c_cscanline[n_c][0]=c_pscanline[n_c][1];
1191
1192                 if ( lossy_undoscanline(c_pscanline[n_c], c_cscanline[n_c], c_columns[n_c], n_c ) != 0 )
1193                 {
1194                   fprintf(stderr,"*** Premature EOF: expected %d rows, got %d\n",rows, n-1);
1195                   found_EOF = 1;
1196                   break;
1197                 }
1198
1199                 write_one_line(c_cscanline[n_c] + 1, c_columns[n_c], c_out[n_c]);
1200
1201                 tot_out += c_columns[n_c];
1202
1203                 /* extend the edges */
1204                 c_cscanline[n_c][c_columns[n_c]+1] = c_cscanline[n_c][c_columns[n_c]];
1205
1206                 /* make the current scanline the previous one */
1207                 c_swaplines(n_c);
1208               }
1209             }  /* End of for loop for each component */
1210
1211             n+=samplingy[whose_max_size_rows];
1212
1213             /* Take out the Restart Markers */
1214             if (got_restart)
1215             {
1216               /* Look for restart markers only after a restart interval */
1217               if ((MCUs_counted % restart_interval) == 0)
1218               {
1219                 bitiflush();
1220                 read_n_bytes(in, 2);  /* read the RST marker */
1221                 bitiinit();
1222               }
1223               MCUs_counted++;
1224               
1225             }
1226
1227           }  /* End of while loop for each line */
1228
1229
1230       }    /* Closes the else, LINE_INT and multi=1 */
1231
1232     }    /* End of part for LINE_INT */
1233
1234     else {    /* Non LINE_INT mode */
1235       if (color_mode==PIXEL_INT) {
1236 /***********************************************************************/
1237 /*           Pixel interleaved mode with single file received          */
1238 /***********************************************************************/
1239
1240         if (lossy==FALSE)
1241         
1242           /* LOSSLESS MODE */
1243           while (++n <= rows)
1244           {
1245             /* 'extend' the edges */
1246             for (n_c=0;n_c<components;n_c++)
1247               cscanline[-components+n_c]=cscanline[n_c]=pscanline[components+n_c];
1248
1249             if ( lossless_undoscanline_pixel(pscanline, cscanline, components*columns) != 0 )
1250             {
1251               fprintf(stderr,"*** Premature EOF: expected %d rows, got %d\n",rows,n-1);
1252               found_EOF = 1;
1253               break;
1254             }
1255
1256             write_one_line(cscanline+components, components*columns, out);
1257     
1258             tot_out += components*columns;
1259
1260             /* extend the edges */
1261             for (n_c=0;n_c<components;n_c++)
1262               cscanline[components*(columns+1)+n_c] = cscanline[components*columns+n_c];
1263
1264             /* make the current scanline the previous one */
1265             swaplines();
1266
1267             /* Take out the Restart Markers */
1268             if (got_restart)
1269             {
1270               /* Look for restart markers only after a restart interval */
1271               if ((MCUs_counted % restart_interval) == 0)
1272               {
1273                 bitiflush();
1274                 read_n_bytes(in, 2);  /* read the RST marker */
1275                 bitiinit();
1276               }
1277               MCUs_counted++;
1278               
1279             }
1280
1281           }  /* End of line loop for PIXEL_INT */
1282
1283
1284         else
1285
1286           /* LOSSY MODE */
1287           while (++n <= rows)
1288           {
1289             /* 'extend' the edges */
1290             for (n_c=0;n_c<components;n_c++)
1291               cscanline[-components+n_c]=cscanline[n_c]=pscanline[components+n_c];
1292
1293             if ( lossy_undoscanline_pixel(pscanline, cscanline, components*columns) != 0 )
1294             {
1295               fprintf(stderr,"*** Premature EOF: expected %d rows, got %d\n",rows,n-1);
1296               found_EOF = 1;
1297               break;
1298             }
1299
1300             write_one_line(cscanline+components, components*columns, out);
1301
1302             tot_out += components*columns;
1303
1304             /* extend the edges */
1305             for (n_c=0;n_c<components;n_c++)
1306               cscanline[components*(columns+1)+n_c] = cscanline[components*columns+n_c];
1307
1308             /* make the current scanline the previous one */
1309             swaplines();
1310
1311             /* Take out the Restart Markers */
1312             if (got_restart)
1313             {
1314               /* Look for restart markers only after a restart interval */
1315               if ((MCUs_counted % restart_interval) == 0)
1316               {
1317                 bitiflush();
1318                 read_n_bytes(in, 2);  /* read the RST marker */
1319                 bitiinit();
1320               }
1321               MCUs_counted++;
1322               
1323             }
1324
1325           }  /* End of line loop for PIXEL_INT */
1326
1327       }
1328       else {
1329 /***********************************************************************/
1330 /*           Plane interleaved mode                */
1331 /***********************************************************************/
1332
1333         if (lossy==FALSE)
1334         
1335           /* LOSSLESS MODE */
1336           while (++n <= c_rows[n_s])
1337           {
1338             /* 'extend' the edges */
1339             c_cscanline[n_s][-1]=c_cscanline[n_s][0]=c_pscanline[n_s][1];
1340
1341             if (lossless_undoscanline(c_pscanline[n_s], c_cscanline[n_s], c_columns[n_s], n_s ) != 0 )
1342             {
1343               fprintf(stderr,"*** Premature EOF: expected %d rows, got %d\n",rows, n-1);
1344               found_EOF = 1;
1345               break;
1346             }
1347
1348             write_one_line(c_cscanline[n_s]+1, c_columns[n_s], c_out[n_s]);
1349
1350             tot_out += c_columns[n_s];
1351
1352             /* extend the edges */
1353             c_cscanline[n_s][c_columns[n_s]+1] = c_cscanline[n_s][c_columns[n_s]];
1354
1355             /* make the current scanline the previous one */
1356             c_swaplines(n_s);
1357
1358             /* Take out the Restart Markers */
1359             if (got_restart)
1360             {
1361               /* Look for restart markers only after a restart interval */
1362               if ((MCUs_counted % restart_interval) == 0)
1363               {
1364                 bitiflush();
1365                 read_n_bytes(in, 2);  /* read the RST marker */
1366                 bitiinit();
1367               }
1368               MCUs_counted++;
1369               
1370             }
1371
1372           }  /* End of line loop in PLANE_INT */
1373         
1374         else
1375
1376           /* LOSSY MODE */
1377           while (++n <= c_rows[n_s])
1378           {
1379             /* 'extend' the edges */
1380             c_cscanline[n_s][-1]=c_cscanline[n_s][0]=c_pscanline[n_s][1];
1381
1382             if (lossy_undoscanline(c_pscanline[n_s], c_cscanline[n_s], c_columns[n_s], n_s ) != 0 )
1383             {
1384               fprintf(stderr,"*** Premature EOF: expected %d rows, got %d\n",rows, n-1);
1385               found_EOF = 1;
1386               break;
1387             }
1388
1389             write_one_line(c_cscanline[n_s]+1, c_columns[n_s], c_out[n_s]);
1390
1391             tot_out += c_columns[n_s];
1392
1393             /* extend the edges */
1394             c_cscanline[n_s][c_columns[n_s]+1] = c_cscanline[n_s][c_columns[n_s]];
1395
1396             /* make the current scanline the previous one */
1397             c_swaplines(n_s);
1398
1399             /* Take out the Restart Markers */
1400             if (got_restart)
1401             {
1402               /* Look for restart markers only after a restart interval */
1403               if ((MCUs_counted % restart_interval) == 0)
1404               {
1405                 bitiflush();
1406                 read_n_bytes(in, 2);  /* read the RST marker */
1407                 bitiinit();
1408               }
1409               MCUs_counted++;
1410               
1411             }
1412
1413           }  /* End of line loop in PLANE_INT */
1414
1415       }  /* End of each component for PLANE_INT */
1416
1417     }  /* End of non LINE_INT */
1418
1419     bitiflush();
1420
1421   } /* End of loop for scans */
1422
1423
1424   mk = 0;
1425
1426   /* Read EOI */
1427   seek_return=seek_marker(in,&mk);
1428   if (seek_return==EOF)
1429   {
1430     fprintf(stderr,"Did not get EOI at end of compressed image\n");
1431     exit(10);
1432   }
1433   if ( seek_return > 2 )
1434   {
1435       fprintf(msgfile,"*** WARNING: %d extra bytes between end of scan and next marker.\n",seek_return-2);
1436       fprintf(msgfile,"***          Added to marker segment count.\n");
1437   }
1438
1439   pos0 += seek_return;
1440   if (mk != EOI)
1441   {
1442     fprintf(stderr,"In this implementation last marker must be EOI\n");
1443     exit(10);
1444   }
1445
1446   if (head_scan[0]->need_table)
1447     fprintf(msgfile,"A mapping table was used which had %i entries of %i bytes each.\n",head_scan[0]->MAXTAB, head_scan[0]->Wt);
1448
1449   if (got_restart)
1450     fprintf(msgfile,"Restart markers were found with a restart interval of %i.\n",restart_interval);
1451
1452   if ( verbose )
1453     fprintf(msgfile,"Marker segment bytes: %ld\n",pos0);
1454
1455   /* position in input file */
1456   pos1 = ftell(in);
1457   /* tot_in = 8*(pos1-pos0); */
1458
1459   /* size of compressed file read (bits), incl. headers. */
1460   tot_in = 8*pos1;
1461
1462   /* Close down */
1463   close_process_run();
1464   closebuffers(multi);
1465
1466
1467   t1 = get_utime();
1468   fprintf(msgfile,"Total bits  in: %ld  Symbols out: %ld  %5.3f bps\n",
1469            tot_in,tot_out,tot_in/(double)tot_out);
1470   fprintf(msgfile,"Time = %1.3f secs : %1.0f KSymbols/sec\n",t1-t0,
1471           (tot_out)/(1024*(t1-t0)));
1472
1473   if ( found_EOF )
1474     exit(0);
1475   else
1476     return 1;
1477 }
1478
1479
1480
1481
1482 void usage()
1483 {
1484   fprintf(stderr,"Usage: %s [flags] [infile] [outfile1 [outfile2, ...]]\n\
1485     DEFAULTS:\n\
1486     infile   = %s.\n\
1487     outfile1 = %s for color image in a single (PPM) output file.\n\
1488     outfile1 = %s for monochrome image in a single (PGM) output file.\n\
1489     outfile[1,2,...] = %s for multiple (PGM) output files \n\
1490     in plane or line interleaved modes.\n",
1491     "locod", "specified JLS file", OUTFILE ".out", 
1492     OUTFILE "1.out",
1493     OUTFILE "[1,2,...].out");
1494   fprintf(stderr,"FLAGS:\n\
1495     outfile2, ... : Multiple output specification for plane or line int. mode.\n\
1496     -i<infile>    : Alternate input specification, use -i- for stdin.\n\
1497     -o<outfile>   : Alternate output specification, use -o- for stdout.\n\
1498     -P            : Generate single (.ppm) output file for sample/line int. mode.\n\
1499     ");
1500   fprintf(stderr,"\
1501     -h            : Print this help.\n\
1502     *** No spaces allowed between a flag and its argument.\n\
1503     ");
1504   
1505 }
1506
1507
1508 void bad_flag(char *s)
1509 {
1510   fprintf(stderr,"Bad flag %s\n",s);
1511   usage();
1512   exit(10);
1513 }
1514