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