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.
10 =========================================================
11 THIS SOFTWARE IS BASED ON HP's implementation of jpeg-ls:
12 =========================================================
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 -------------------------------------------------------------------------------
42 /* decoder.c --- the main module, argument parsing, file I/O
44 * Initial code by Alex Jakulin, Aug. 1995
46 * Modified and optimized: Gadiel Seroussi, October 1995
48 * Color Enhancement: Guillermo Sapiro, August 1996
50 * Modified and added Restart marker and input tables by:
51 * David Cheng-Hsiu Chu, and Ismail R. Ismail march 1999
58 #define PGMNAME PGMPREFIX "d"
59 #define EPGMNAME PGMPREFIX "e"
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\
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";
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];
83 jpeg_ls_header *head_frame, *head_scan[MAX_SCANS];
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;
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 */
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 */
113 int alpha, /* alphabet size */
114 ceil_half_alpha; /* ceil(alpha/2) */
127 /* Write one row of pixel values */
128 inline void write_one_line(pixel* line, int cols, FILE* outfile)
132 unsigned int* maptable;
134 /* No mapping tables used */
135 if(!(head_scan[0]->need_table))
138 unsigned char* line8;
139 line8 = (unsigned char*)safealloc(cols);
141 for (i=0; i< cols; i++)
142 *(line8+i)=ENDIAN8(*(line+i));
144 fwrite(line8, sizeof(unsigned char), cols, outfile);
148 fwrite(line, sizeof(short), cols, outfile);
151 /* Mapping tables used */
156 /* Write one byte per table entry */
157 if (head_scan[0]->Wt == 1)
159 unsigned char* line8;
160 line8 = (unsigned char*)safealloc(cols); /* If don't have 2, it mallocs over the table? */
162 maptable = head_scan[0]->TABLE[head_scan[0]->TID];
164 for (i=0; i<cols; i++)
167 *(line8+i) = ENDIAN8(maptable[index]);
170 fwrite(line8, sizeof(unsigned char), cols, outfile);
174 /* Write two bytes per table entry */
175 else if (head_scan[0]->Wt == 2)
177 unsigned short* line16;
178 line16 = (unsigned short*)safealloc(cols*2);
180 maptable = head_scan[0]->TABLE[head_scan[0]->TID];
182 for (i=0; i<cols; i++)
185 *(line16+i) = (unsigned short) maptable[index];
188 fwrite(line16, sizeof(short), cols, outfile);
192 /* Write three bytes per table entry */
193 else if (head_scan[0]->Wt == 3)
195 unsigned char* line8_3;
196 line8_3 = (unsigned char*)safealloc(cols*3);
198 maptable = head_scan[0]->TABLE[head_scan[0]->TID];
200 for (i=0; i<cols; i++)
203 *(line8_3 + (i*3)) = (unsigned char) (maptable[index] >> 16);
204 *(line8_3 + (i*3) + 1) = (unsigned char) (maptable[index] >> 8);
205 *(line8_3 + (i*3) + 2) = (unsigned char) (maptable[index]);
208 fwrite(line8_3, sizeof(char), cols*3, outfile);
214 /* Can't do 16 bit index values */
218 fprintf(stderr, "Sorry, mapping tables are only supported for 8 bpp images in this implementation.\n");
230 void initbuffers(int multi, int comp) {
234 if (multi) /* Output to several files */
236 for (i=0;i<comp;i++) {
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) );
241 /* Adjust scan line pointers taking into account the margins,
242 and also the fact that indexing for scan lines starts from 1
244 c_pscanline[i] = c_pscanl0[i] + (LEFTMARGIN-1);
245 c_cscanline[i] = c_cscanl0[i] + (LEFTMARGIN-1);
248 else { /* Output to a single file */
250 pscanl0 = (pixel *)safecalloc(components*(columns+LEFTMARGIN+RIGHTMARGIN), sizeof(pixel) );
251 cscanl0 = (pixel *)safecalloc(components*(columns+LEFTMARGIN+RIGHTMARGIN), sizeof(pixel) );
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)
257 pscanline = pscanl0 + components*(LEFTMARGIN-1);
258 cscanline = cscanl0 + components*(LEFTMARGIN-1);
271 pscanline = pscanl0 + components*(LEFTMARGIN-1);
272 cscanline = cscanl0 + components*(LEFTMARGIN-1);
275 void c_swaplines(int i)
279 c_pscanl0[i] = c_cscanl0[i];
281 c_pscanline[i] = c_pscanl0[i] + (LEFTMARGIN-1);
282 c_cscanline[i] = c_cscanl0[i] + (LEFTMARGIN-1);
285 void closebuffers(int multi) {
293 for (i=0;i<components;i++)
303 int initialize(int argc, char *argv[]) {
304 char *infilename = NULL,
305 *outfilename = OUTFILE ".out",
306 *c_outfilename[MAX_COMPONENTS],
308 int i, max_samp_columns, max_samp_rows, mk, n_s,
315 int pos; /* position in the file, after the header */
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);
323 for ( i=1; i<argc; i++ )
324 if ( argv[i][0] == '-' )
326 switch ( argv[i][1] ) {
329 infilename = argv[i]+2;
334 outfilename = c_outfilename[out_files++] = argv[i]+2;
343 if ( sscanf(argv[i],"-v%d",&verbose) != 1 )
354 infilename = argv[i];
357 else if ( ! gotoutf )
358 outfilename = c_outfilename[out_files++] = argv[i];
362 verbose = 1; /* at least the banner will show */
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");
370 if ( infilename == NULL ) {
375 if ( strcmp(infilename,"-")==0 )
377 else if ( (in=fopen(infilename,"rb")) == NULL ) {
383 /* Read the compressed image frame header */
386 head_frame = (jpeg_ls_header *) safecalloc(1,sizeof(jpeg_ls_header));
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;
395 seek_return = seek_marker(in,&mk);
396 if (seek_return == EOF) {
397 fprintf(stderr,"*** Premature End of File seeking SOI\n");
403 fprintf(stderr,"Marker %04x found: first marker must be SOI (%04x) in this implementation\n", mk, SOI);
409 seek_return = seek_marker(in,&mk);
410 if (seek_return == EOF) {
411 fprintf(stderr,"*** Premature End of File seeking SOF_LS\n");
415 pos += seek_return; /* Read SOF_LS */
417 fprintf(stderr,"Marker %04x found: second marker must be SOF_LS (%04x) in this implementation\n", mk, SOF_LS);
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");
431 head_scan[0]->alp = head_frame->alp; /* default alpha */
434 /* LSE Extension header */
435 /* This version supports only 2 extension headers, and 1 set of
436 parameters for all the scans */
438 head_scan[0]->need_table = 0;
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");
453 seek_return = read_jpegls_extmarker(in, head_scan[0]);
454 if (seek_return == EOF) {
455 fprintf(stderr,"*** Premature End of File\n");
463 seek_return = read_jpegls_restartmarker(in, head_scan[0]);
466 restart_interval = head_scan[0]->restart_interval;
474 /* End of extension header */
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");
486 shift=head_scan[0]->shift;
488 fprintf(stderr,"Got shift = %d != 0 : not implemented.\n",shift);
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;
500 if (color_mode==PLANE_INT)
501 number_of_scans=components;
505 set_thresholds(head_scan[0]->alp, head_scan[0]->NEAR, &(head_scan[0]->T1), &(head_scan[0]->T2), &(head_scan[0]->T3));
511 RESET=head_scan[0]->RES;
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);
519 /* Check to see if lossless or lossy */
525 /* Check for 16 or 8 bit mode */
526 if (alpha0 <= MAXA16 && alpha0 > MAXA8)
532 else if (alpha0 <= MAXA8 && alpha0 >= 1)
539 fprintf(stderr,"Got alpha = %d\n",alpha0+1);
540 error("Bad value for alpha. Sorry...\n");
544 check_compatibility(head_frame,head_scan[0],0);
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))
551 fprintf(stderr,"\nERROR: Cannot use -P (PPM output) with subsampled compressed components\n");
556 if ((!multi) && (color_mode==PLANE_INT))
559 fprintf(stderr,"\nERROR: Cannot use -P (PPM output) with plane intereleaved mode\n");
565 if ((multi) && (color_mode==PIXEL_INT)) {
566 multi = 0; /* equivalent to specifying -P flag */
569 if ((out_files>1) && (color_mode==PIXEL_INT)) {
570 fprintf(stderr,"ERROR: Pixel interleaved mode uses only 1 output file\n");
574 if ((multi) && (out_files) && (out_files!=components)) {
575 fprintf(stderr,"ERROR: Number of files, %d, for output must be equal to number of image components, %d\n",out_files,components);
579 /* Compute the image size for the different components */
581 c_columns[0]=columns;
583 whose_max_size_rows=0;
590 for(i=0;i<components;i++) {
591 if (samplingx[i]>max_samp_columns) {
592 max_samp_columns=samplingx[i];
593 whose_max_size_columns=i;
595 if (samplingy[i]>max_samp_rows) {
596 max_samp_rows=samplingy[i];
597 whose_max_size_rows=i;
601 c_columns[whose_max_size_columns]=columns;
602 c_rows[whose_max_size_rows]=rows;
604 for(i=0;i<components;i++) {
605 if (i!=whose_max_size_columns)
607 c_columns[i]=c_columns[whose_max_size_columns]*samplingx[i];
608 c_columns[i]/=samplingx[whose_max_size_columns];
610 if (i!=whose_max_size_rows) {
611 c_rows[i]=c_rows[whose_max_size_rows]*samplingy[i];
612 c_rows[i]/=samplingy[whose_max_size_rows];
618 /* msgfile seems to start being used here, let's initialize it here */
619 if ( !msgfile ) msgfile = stdout;
621 if ( outfilename == NULL ) {
626 if ( strcmp(outfilename,"-")==0 ) {
632 if ( (out=fopen(outfilename,"wb")) == NULL ) {
638 for (i=0;i<components;i++)
639 if ( (c_out[i]=fopen(c_outfilename[i],"wb")) == NULL )
641 perror(c_outfilename[i]);
649 /* check that color mode is valid and pick color mode string */
650 switch ( color_mode ) {
653 color_mode_string = plane_int_string;
657 color_mode_string = line_int_string;
661 color_mode_string = pixel_int_string;
665 fprintf(stderr,"ERROR: Invalid color mode %d\n",color_mode);
671 fprintf(msgfile,"%s\n",banner);
676 fprintf(msgfile,"Input file: %s\nOutput file: %s\n",infilename,outfilename);
679 fprintf(msgfile,"Input file: %s\nOutput files: ",infilename);
680 for (i=0;i<components;i++)
681 fprintf(msgfile," %s ",c_outfilename[i]);
682 fprintf(msgfile,"\n");
687 if ( alpha0 != alpha ) {
688 fprintf(stderr, "Sorry, this version has been optimized for alphabet size = %d, got %d\n",alpha,alpha0);
693 ceil_half_alpha = (alpha+1)/2;
698 /* check that alpha is a power of 2 */
699 for ( alpha0=alpha, i=-1; alpha0; alpha0>>=1, i++);
700 if ( alpha != (1<<i) ) {
701 fprintf(stderr, "Sorry, this version has been optimized for alphabet size = power of 2, got %d\n",alpha);
708 /* compute auxiliary parameters for near-lossless (globals) */
710 qbeta = (alpha + 2*NEAR + quant-1 )/quant;
712 ceil_half_qbeta = (qbeta+1)/2;
714 alpha1eps = alpha-1+NEAR;
715 fprintf(msgfile,"Near-lossless mode: NEAR = %d beta = %d qbeta = %d\n",NEAR,beta,qbeta);
718 /* compute bits per sample for input symbols */
719 for ( bpp=1; (1L<<bpp)<alpha; bpp++ );
721 /* compute bits per sample for unencoded prediction errors */
723 for ( qbpp=1; (1L<<qbpp)<qbeta; qbpp++ );
727 if ( bpp < 2 ) bpp = 2;
729 /* limit for unary part of Golomb code */
731 limit = 2*(bpp + 8) - qbpp -1;
733 limit = 4*bpp - qbpp - 1;
735 /* print out parameters */
738 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",
739 columns, rows, alpha0, components,
740 color_mode, color_mode_string,
741 T1, T2, T3, RESET,limit);
743 fprintf(msgfile,"Image: cols=");
744 for (i=0;i<components;i++)
745 fprintf(msgfile," %d",c_columns[i]);
746 fprintf(msgfile," rows=");
747 for (i=0;i<components;i++)
748 fprintf(msgfile," %d",c_rows[i]);
749 fprintf(msgfile," alpha=%d comp=%d mode=%d (%s)\nParameters: Ta=%d Tb=%d Tc=%d RESET=%d limit=%d",
751 color_mode, color_mode_string,
752 T1, T2, T3,RESET,limit);
757 fprintf(msgfile,"\n");
760 /* Write out the image header for PGM or PPM files */
761 /* Must look at if there are Mapping Tables used */
763 /* No Mapping Tables used */
764 if (!head_scan[0]->need_table)
767 if (components==1) fputs("P5\n", out);
768 else if (components==3) fputs("P6\n", out);
769 else if (components==4) fputs("P7\n", out);
770 else fprintf(out,"P%d\n",10+components);
772 fprintf(out,"%d %d\n", columns, rows);
773 fprintf(out,"%d\n", alpha - 1);
776 for (i=0;i<components;i++) {
777 fputs("P5\n", c_out[i]);
778 fprintf(c_out[i],"%d %d\n", c_columns[i], c_rows[i]);
779 fprintf(c_out[i],"%d\n", alpha - 1);
783 /* Mapping Tables used */
786 /* only 8 bit indexes supported for mapping tables */
789 fprintf(stderr, "Sorry, mapping tables are only supported for 8 bpp images in this implementation.\n");
793 /* Mapping Table elements are 1 or 2 bytes */
794 if (head_scan[0]->Wt==1 || head_scan[0]->Wt==2)
797 if (head_scan[0]->Wt==1)
800 alpha_temp = alpha*alpha;
804 if (components==1) fputs("P5\n", out);
805 else if (components==3) fputs("P6\n", out);
806 else if (components==4) fputs("P7\n", out);
807 else fprintf(out,"P%d\n",10+components);
809 fprintf(out,"%d %d\n", columns, rows);
810 fprintf(out,"%d\n", alpha_temp - 1);
813 for (i=0;i<components;i++)
815 fputs("P5\n", c_out[i]);
816 fprintf(c_out[i],"%d %d\n", c_columns[i], c_rows[i]);
817 fprintf(c_out[i],"%d\n", alpha_temp - 1);
821 /* Mapping Table elements are 3 bytes */
822 else if (head_scan[0]->Wt==3)
826 if (components==1) fputs("P6\n", out);
829 fprintf(stderr,"Error : Cannot have a multi-component image and a mapping table with 3 bytes per element.\n");
833 fprintf(out,"%d %d\n", columns, rows);
834 fprintf(out,"%d\n", alpha - 1);
837 for (i=0;i<components;i++)
839 fputs("P6\n", c_out[i]);
840 fprintf(c_out[i],"%d %d\n", c_columns[i], c_rows[i]);
841 fprintf(c_out[i],"%d\n", alpha - 1);
845 /* Mapping Table elements aren't 1 to 3 bytes */
848 fprintf(stderr, "Sorry, mapping tables elements can only be 1 to 3 bytes in this implementation.\n");
854 /* Allocate memory pools. */
855 initbuffers(multi, components);
858 /* return size of the header, in bytes */
867 /* Main loop for decoding files */
869 int main (int argc, char *argv[]) {
870 int n,n_c,n_r,my_i,n_s,mk,seek_return;
872 double t0, t1; /*, get_utime();*/
876 pixel *local_scanl0,*local_scanl1,*local_pscanline,*local_cscanline;
880 /* Parse the parameters, initialize */
881 /* Not yet fully implemented */
883 pos0 = initialize(argc, argv);
886 /* start timer (must be AFTER initialize()) */
890 /* Initialize the scanline buffers */
892 for (n = 0; n <= (columns + 1); ++n)
895 for (n_c=0;n_c<components;n_c++)
896 for (n = 0; n <= (c_columns[n_c] + 1); ++n)
897 c_pscanline[n_c][n] = 0;
899 if ((components>1) && (multi==0))
901 /* OUTPUT PPM file, allocate auxiliary buffers */
902 local_scanl0 = (pixel *)safecalloc(columns+LEFTMARGIN+RIGHTMARGIN,sizeof (pixel) );
903 local_scanl1 = (pixel *)safecalloc(columns+LEFTMARGIN+RIGHTMARGIN,sizeof (pixel) );
905 local_pscanline = local_scanl0 + LEFTMARGIN-1;
906 local_cscanline = local_scanl1 + LEFTMARGIN-1;
910 for (n_s=0;n_s<number_of_scans;n_s++)
912 /* Repeat prediction/quantization/statistics scanline by scanline,
915 /* Reset Restart Markers for every scan */
918 /* This implementation supports parameters in 1st scan */
921 /* Prepare the quantization LUTs */
925 /* prepare div/mul tables for near-lossless quantization */
926 prepare_qtables(alpha,NEAR);
930 { /* Read further scan headers */
931 seek_return=seek_marker(in,&mk);
932 if (seek_return == EOF)
934 fprintf(stderr,"*** Premature End of File seeking SOS marker\n");
937 if ( seek_return > 2 )
939 fprintf(msgfile,"*** WARNING: %d extra bytes between end of scan and next marker.\n",seek_return-2);
940 fprintf(msgfile,"*** Added to marker segment count.\n");
945 fprintf(stderr,"Expecting SOS (%04x), got %04x\n",SOS,mk);
948 seek_return = read_jpegls_scan(in,head_scan[n_s]); /* Read the scan header*/
949 if (seek_return == EOF)
951 fprintf(stderr,"*** Premature End of File reading scan marker segment\n");
955 if (head_scan[n_s]->shift!=0)
957 fprintf(stderr,"Got shift = %d != 0 : not implemented.\n",head_scan[n_s]->shift);
960 if (head_scan[n_s]->NEAR != NEAR)
962 fprintf(stderr,"Got NEAR=%d after NEAR=%d: cannot change parameters between scans in this implementation\n",head_scan[n_s]->NEAR,NEAR);
965 if ((head_scan[n_s]->color_mode != PLANE_INT) || (head_scan[n_s]->comp != 1) ||
966 (head_scan[n_s]->comp_ids[0] != n_s+1))
968 fprintf(stderr,"This implementation supports multiple scans only in PLANE INTERLEAVED mode.\n");
973 /* Initializations for each scan */
976 /* Start from 1st image row */
979 /* Initialize stats arrays */
985 /* Initialize run processing */
986 init_process_run(MAXRUN);
988 if (color_mode==LINE_INT) { /* line int. */
990 /***********************************************************************/
991 /* Line interleaved mode with single file received */
992 /***********************************************************************/
999 /* 'extend' the edges */
1000 for (n_c=0;n_c<components;n_c++)
1001 cscanline[-components+n_c]=cscanline[n_c]=pscanline[components+n_c];
1003 for (n_c=0;n_c<components;n_c++)
1006 for (my_i=0;my_i<columns+LEFTMARGIN+RIGHTMARGIN;my_i++)
1008 local_cscanline[-1+my_i]=cscanline[-components+my_i*components+n_c];
1009 local_pscanline[-1+my_i]=pscanline[-components+my_i*components+n_c];
1013 local_cscanline=cscanline;
1014 local_pscanline=pscanline;
1017 if ( lossless_undoscanline(local_pscanline, local_cscanline, columns, n_c ) != 0 )
1019 fprintf(stderr,"*** Premature EOF: expected %d rows, got %d\n",rows, n-1);
1025 for (my_i=0;my_i<columns+LEFTMARGIN+RIGHTMARGIN;my_i++)
1026 cscanline[-components+my_i*components+n_c]=local_cscanline[-1+my_i];
1029 write_one_line(cscanline + components, components*columns, out);
1031 tot_out += components*columns;
1033 /* extend the edges */
1034 for (n_c=0;n_c<components;n_c++)
1035 cscanline[components*(columns+1)+n_c] = cscanline[components*columns+n_c];
1037 /* make the current scanline the previous one */
1040 /* Take out the Restart Markers */
1043 /* Look for restart markers only after a restart interval */
1044 if ((MCUs_counted % restart_interval) == 0)
1047 read_n_bytes(in, 2); /* read the RST marker */
1054 } /* End of while loop for each file line */
1061 /* 'extend' the edges */
1062 for (n_c=0;n_c<components;n_c++)
1063 cscanline[-components+n_c]=cscanline[n_c]=pscanline[components+n_c];
1065 for (n_c=0;n_c<components;n_c++)
1068 for (my_i=0;my_i<columns+LEFTMARGIN+RIGHTMARGIN;my_i++)
1070 local_cscanline[-1+my_i]=cscanline[-components+my_i*components+n_c];
1071 local_pscanline[-1+my_i]=pscanline[-components+my_i*components+n_c];
1075 local_cscanline=cscanline;
1076 local_pscanline=pscanline;
1079 if ( lossy_undoscanline(local_pscanline, local_cscanline, columns, n_c ) != 0 )
1081 fprintf(stderr,"*** Premature EOF: expected %d rows, got %d\n",rows, n-1);
1087 for (my_i=0;my_i<columns+LEFTMARGIN+RIGHTMARGIN;my_i++)
1088 cscanline[-components+my_i*components+n_c]=local_cscanline[-1+my_i];
1091 write_one_line(cscanline + components, components*columns, out);
1093 tot_out += components*columns;
1095 /* extend the edges */
1096 for (n_c=0;n_c<components;n_c++)
1097 cscanline[components*(columns+1)+n_c] = cscanline[components*columns+n_c];
1099 /* make the current scanline the previous one */
1102 /* Take out the Restart Markers */
1105 /* Look for restart markers only after a restart interval */
1106 if ((MCUs_counted % restart_interval) == 0)
1109 read_n_bytes(in, 2); /* read the RST marker */
1116 } /* End of while loop for each file line */
1120 { /* Multiple files */
1121 /* color_mode==LINE_INT and multi==1 */
1122 /***********************************************************************/
1123 /* Line interleaved mode with multiple files received */
1124 /***********************************************************************/
1131 while (n <= c_rows[whose_max_size_rows])
1133 for (n_c=0;n_c<components;n_c++)
1135 for (n_r=0;n_r<samplingy[n_c];n_r++)
1138 /* 'extend' the edges */
1139 c_cscanline[n_c][-1]=c_cscanline[n_c][0]=c_pscanline[n_c][1];
1141 if ( lossless_undoscanline(c_pscanline[n_c], c_cscanline[n_c], c_columns[n_c], n_c ) != 0 )
1143 fprintf(stderr,"*** Premature EOF: expected %d rows, got %d\n",rows, n-1);
1148 write_one_line(c_cscanline[n_c] + 1, c_columns[n_c], c_out[n_c]);
1150 tot_out += c_columns[n_c];
1152 /* extend the edges */
1153 c_cscanline[n_c][c_columns[n_c]+1] = c_cscanline[n_c][c_columns[n_c]];
1155 /* make the current scanline the previous one */
1158 } /* End of for loop for each component */
1160 n+=samplingy[whose_max_size_rows];
1162 /* Take out the Restart Markers */
1165 /* Look for restart markers only after a restart interval */
1166 if ((MCUs_counted % restart_interval) == 0)
1169 read_n_bytes(in, 2); /* read the RST marker */
1176 } /* End of while loop for each line */
1181 while (n <= c_rows[whose_max_size_rows])
1183 for (n_c=0;n_c<components;n_c++)
1185 for (n_r=0;n_r<samplingy[n_c];n_r++)
1188 /* 'extend' the edges */
1189 c_cscanline[n_c][-1]=c_cscanline[n_c][0]=c_pscanline[n_c][1];
1191 if ( lossy_undoscanline(c_pscanline[n_c], c_cscanline[n_c], c_columns[n_c], n_c ) != 0 )
1193 fprintf(stderr,"*** Premature EOF: expected %d rows, got %d\n",rows, n-1);
1198 write_one_line(c_cscanline[n_c] + 1, c_columns[n_c], c_out[n_c]);
1200 tot_out += c_columns[n_c];
1202 /* extend the edges */
1203 c_cscanline[n_c][c_columns[n_c]+1] = c_cscanline[n_c][c_columns[n_c]];
1205 /* make the current scanline the previous one */
1208 } /* End of for loop for each component */
1210 n+=samplingy[whose_max_size_rows];
1212 /* Take out the Restart Markers */
1215 /* Look for restart markers only after a restart interval */
1216 if ((MCUs_counted % restart_interval) == 0)
1219 read_n_bytes(in, 2); /* read the RST marker */
1226 } /* End of while loop for each line */
1229 } /* Closes the else, LINE_INT and multi=1 */
1231 } /* End of part for LINE_INT */
1233 else { /* Non LINE_INT mode */
1234 if (color_mode==PIXEL_INT) {
1235 /***********************************************************************/
1236 /* Pixel interleaved mode with single file received */
1237 /***********************************************************************/
1244 /* 'extend' the edges */
1245 for (n_c=0;n_c<components;n_c++)
1246 cscanline[-components+n_c]=cscanline[n_c]=pscanline[components+n_c];
1248 if ( lossless_undoscanline_pixel(pscanline, cscanline, components*columns) != 0 )
1250 fprintf(stderr,"*** Premature EOF: expected %d rows, got %d\n",rows,n-1);
1255 write_one_line(cscanline+components, components*columns, out);
1257 tot_out += components*columns;
1259 /* extend the edges */
1260 for (n_c=0;n_c<components;n_c++)
1261 cscanline[components*(columns+1)+n_c] = cscanline[components*columns+n_c];
1263 /* make the current scanline the previous one */
1266 /* Take out the Restart Markers */
1269 /* Look for restart markers only after a restart interval */
1270 if ((MCUs_counted % restart_interval) == 0)
1273 read_n_bytes(in, 2); /* read the RST marker */
1280 } /* End of line loop for PIXEL_INT */
1288 /* 'extend' the edges */
1289 for (n_c=0;n_c<components;n_c++)
1290 cscanline[-components+n_c]=cscanline[n_c]=pscanline[components+n_c];
1292 if ( lossy_undoscanline_pixel(pscanline, cscanline, components*columns) != 0 )
1294 fprintf(stderr,"*** Premature EOF: expected %d rows, got %d\n",rows,n-1);
1299 write_one_line(cscanline+components, components*columns, out);
1301 tot_out += components*columns;
1303 /* extend the edges */
1304 for (n_c=0;n_c<components;n_c++)
1305 cscanline[components*(columns+1)+n_c] = cscanline[components*columns+n_c];
1307 /* make the current scanline the previous one */
1310 /* Take out the Restart Markers */
1313 /* Look for restart markers only after a restart interval */
1314 if ((MCUs_counted % restart_interval) == 0)
1317 read_n_bytes(in, 2); /* read the RST marker */
1324 } /* End of line loop for PIXEL_INT */
1328 /***********************************************************************/
1329 /* Plane interleaved mode */
1330 /***********************************************************************/
1335 while (++n <= c_rows[n_s])
1337 /* 'extend' the edges */
1338 c_cscanline[n_s][-1]=c_cscanline[n_s][0]=c_pscanline[n_s][1];
1340 if (lossless_undoscanline(c_pscanline[n_s], c_cscanline[n_s], c_columns[n_s], n_s ) != 0 )
1342 fprintf(stderr,"*** Premature EOF: expected %d rows, got %d\n",rows, n-1);
1347 write_one_line(c_cscanline[n_s]+1, c_columns[n_s], c_out[n_s]);
1349 tot_out += c_columns[n_s];
1351 /* extend the edges */
1352 c_cscanline[n_s][c_columns[n_s]+1] = c_cscanline[n_s][c_columns[n_s]];
1354 /* make the current scanline the previous one */
1357 /* Take out the Restart Markers */
1360 /* Look for restart markers only after a restart interval */
1361 if ((MCUs_counted % restart_interval) == 0)
1364 read_n_bytes(in, 2); /* read the RST marker */
1371 } /* End of line loop in PLANE_INT */
1376 while (++n <= c_rows[n_s])
1378 /* 'extend' the edges */
1379 c_cscanline[n_s][-1]=c_cscanline[n_s][0]=c_pscanline[n_s][1];
1381 if (lossy_undoscanline(c_pscanline[n_s], c_cscanline[n_s], c_columns[n_s], n_s ) != 0 )
1383 fprintf(stderr,"*** Premature EOF: expected %d rows, got %d\n",rows, n-1);
1388 write_one_line(c_cscanline[n_s]+1, c_columns[n_s], c_out[n_s]);
1390 tot_out += c_columns[n_s];
1392 /* extend the edges */
1393 c_cscanline[n_s][c_columns[n_s]+1] = c_cscanline[n_s][c_columns[n_s]];
1395 /* make the current scanline the previous one */
1398 /* Take out the Restart Markers */
1401 /* Look for restart markers only after a restart interval */
1402 if ((MCUs_counted % restart_interval) == 0)
1405 read_n_bytes(in, 2); /* read the RST marker */
1412 } /* End of line loop in PLANE_INT */
1414 } /* End of each component for PLANE_INT */
1416 } /* End of non LINE_INT */
1420 } /* End of loop for scans */
1426 seek_return=seek_marker(in,&mk);
1427 if (seek_return==EOF)
1429 fprintf(stderr,"Did not get EOI at end of compressed image\n");
1432 if ( seek_return > 2 )
1434 fprintf(msgfile,"*** WARNING: %d extra bytes between end of scan and next marker.\n",seek_return-2);
1435 fprintf(msgfile,"*** Added to marker segment count.\n");
1438 pos0 += seek_return;
1441 fprintf(stderr,"In this implementation last marker must be EOI\n");
1445 if (head_scan[0]->need_table)
1446 fprintf(msgfile,"A mapping table was used which had %i entries of %i bytes each.\n",head_scan[0]->MAXTAB, head_scan[0]->Wt);
1449 fprintf(msgfile,"Restart markers were found with a restart interval of %i.\n",restart_interval);
1452 fprintf(msgfile,"Marker segment bytes: %ld\n",pos0);
1454 /* position in input file */
1456 /* tot_in = 8*(pos1-pos0); */
1458 /* size of compressed file read (bits), incl. headers. */
1462 close_process_run();
1463 closebuffers(multi);
1467 fprintf(msgfile,"Total bits in: %ld Symbols out: %ld %5.3lf bps\n",
1468 tot_in,tot_out,tot_in/(double)tot_out);
1469 fprintf(msgfile,"Time = %1.3lf secs : %1.0lf KSymbols/sec\n",t1-t0,
1470 (tot_out)/(1024*(t1-t0)));
1483 fprintf(stderr,"Usage: %s [flags] [infile] [outfile1 [outfile2, ...]]\n\
1486 outfile1 = %s for color image in a single (PPM) output file.\n\
1487 outfile1 = %s for monochrome image in a single (PGM) output file.\n\
1488 outfile[1,2,...] = %s for multiple (PGM) output files \n\
1489 in plane or line interleaved modes.\n",
1490 "locod", "specified JLS file", OUTFILE ".out",
1492 OUTFILE "[1,2,...].out");
1493 fprintf(stderr,"FLAGS:\n\
1494 outfile2, ... : Multiple output specification for plane or line int. mode.\n\
1495 -i<infile> : Alternate input specification, use -i- for stdin.\n\
1496 -o<outfile> : Alternate output specification, use -o- for stdout.\n\
1497 -P : Generate single (.ppm) output file for sample/line int. mode.\n\
1500 -h : Print this help.\n\
1501 *** No spaces allowed between a flag and its argument.\n\
1507 void bad_flag(char *s)
1509 fprintf(stderr,"Bad flag %s\n",s);