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