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