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