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