1 /* SPMG/JPEG-LS IMPLEMENTATION V.2.1
2 =====================================
3 These programs are Copyright (c) University of British Columbia. All rights 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 /* encoder.c --- the main module, argument parsing, file I/O
45 * Initial code by Alex Jakulin, Aug. 1995
47 * Modified and optimized: Gadiel Seroussi, October 1995
49 * Color Enhancement: Guillermo Sapiro, August 1996
51 * Modified and added Restart marker and input tables by:
52 * David Cheng-Hsiu Chu, and Ismail R. Ismail march 1999
60 static char *banner="\n\
61 =============================================\n\
62 SPMG/JPEG-LS COMPRESSOR " JPEGLSVERSION "\n\
63 =============================================\n\
64 These programs are Copyright (c) University of British Columbia.\n\
65 All rights reserved. They may be freely redistributed in their\n\
66 entirety provided that this copyright notice is not removed.\n\
67 They may not be sold for profit or incorporated in commercial\n\
68 programs without the written permission of the copyright holder.\n\
69 Each program is provided as is, without any express or implied\n\
70 warranty, without even the warranty of fitness for a particular\n\
73 =========================================================\n\
74 THIS SOFTWARE IS BASED ON HP's implementation of jpeg-ls:\n\
75 =========================================================\n\
76 (c) COPYRIGHT HEWLETT-PACKARD COMPANY, 1995-1999.\n";
78 pixel *pscanline, *cscanline, *scanl0, *scanl1;
79 pixel *c_pscanline[MAX_COMPONENTS], *c_cscanline[MAX_COMPONENTS],
80 *c_scanl0[MAX_COMPONENTS], *c_scanl1[MAX_COMPONENTS];
82 jpeg_ls_header *head_frame,*head_scan[MAX_SCANS];
84 int columns, rows, components,
85 samplingx[MAX_COMPONENTS], samplingy[MAX_COMPONENTS];
86 int c_columns[MAX_COMPONENTS];
87 int c_rows[MAX_COMPONENTS];
88 int whose_max_size_rows, whose_max_size_columns;
90 int need_lse; /* if we need an LSE marker (non-default params) */
91 int need_table; /* if we need an LSE marker (mapping table) */
92 int need_restart; /* if we need to add restart markers */
93 int restart_interval; /* indicates the restart interval */
94 int multi; /* if the files are separate */
95 int application_header; /* application bytes written in the header */
96 int all_header; /* all bytes of the header, including application
97 bytes and JPEG-LS bytes */
98 int shift=0; /* Shift value for sparse images */
99 int palete=0; /* for paletized images */
100 int lossy; /* Indicates if in lossy mode or not */
101 int lutmax; /* lutmax is either 256 or 4501 */
102 int bpp16; /* Indicates if 16 bits per pixel mode or not */
103 char *mappingtablefilename=NULL; /* Mapping table filename */
113 int alpha, /* alphabet size */
114 ceil_half_alpha; /* ceil(alpha/2) */
124 /* Read one row of pixel values */
126 inline void read_one_line(pixel* line, int cols, FILE* infile)
128 unsigned char* line8;
133 line8 = (unsigned char *)safealloc(cols);
135 if (fread(line8, 1, cols, infile) != cols)
136 fprintf(stderr,"Input file is truncated");
138 for(i=0; i<cols; i++)
145 if (fread(line, 2, cols, infile) != cols)
146 fprintf(stderr,"Input file is truncated");
155 /* Initialize the buffers for each line */
156 void initbuffers(int multi, int comp) {
160 if (multi) /* The files are received independent */
162 for (i=0;i<comp;i++) {
163 c_scanl0[i] = (pixel *)safecalloc((c_columns[i]+LEFTMARGIN+RIGHTMARGIN), sizeof(pixel) );
164 c_scanl1[i] = (pixel *)safecalloc((c_columns[i]+LEFTMARGIN+RIGHTMARGIN), sizeof(pixel) );
166 c_pscanline[i] = c_scanl0[i] + (LEFTMARGIN-1);
167 c_cscanline[i] = c_scanl1[i] + (LEFTMARGIN-1);
170 else { /* Only 1 file received */
172 scanl0 = (pixel *)safecalloc(components*(columns+LEFTMARGIN+RIGHTMARGIN), sizeof(pixel) );
173 scanl1 = (pixel *)safecalloc(components*(columns+LEFTMARGIN+RIGHTMARGIN), sizeof(pixel) );
175 /* Adjust scan line pointers taking into account the margins,
176 and also the fact that indexing for scan lines starts from 1
178 pscanline = scanl0 + components*(LEFTMARGIN-1);
179 cscanline = scanl1 + components*(LEFTMARGIN-1);
188 /* Swap the pointers to the current and previous scanlines */
194 pscanline = cscanline;
201 /* Swap the pointers to the current and previous scanlines */
203 void c_swaplines(int i)
206 temp = c_pscanline[i];
207 c_pscanline[i] = c_cscanline[i];
208 c_cscanline[i] = temp;
213 /* close the line buffers */
214 int closebuffers(int multi) {
222 for (i=0;i<components;i++)
238 /* Initialization Function - Reads in parameters from image and command line */
240 void initialize(int argc, char *argv[])
242 char *infilename=NULL,
243 *c_infilename[MAX_COMPONENTS],
244 *outfilename = OUTFILE COMPSUFFIX,
246 int i, n_c, common_rows, common_alpha,
247 min_size_rows, min_size_columns,
256 color_mode=DEFAULT_COLOR_MODE;
267 /* Initialize NEAR to zero and loss-less mode */
271 /* Go through the arguments in command line */
272 for ( i=1; i<argc; i++ )
273 if ( argv[i][0] == '-' ) {
274 switch ( argv[i][1] ) {
276 /* Enable use of Restart Markers */
279 if ( sscanf(argv[i]+2,"%d",&restart_interval) != 1 ) {
284 /* Enable use of Mapping Tables */
287 mappingtablefilename = argv[i]+2;
292 if ( sscanf(argv[i]+2,"%d",&temp_reset) != 1 ) {
295 if ( temp_reset != DEFAULT_RESET ) {
298 fprintf(stderr,"ERROR: This version compiled with fixed RESET = %d, got %d\n",DEFAULT_RESET,temp_reset);
308 if ( sscanf(argv[i]+2,"%d",&color_mode) != 1 ) {
315 if ( sscanf(argv[i]+2,"%d",&shift) != 1 ) {
319 fprintf(stderr,"Sorry, sparse mode not implemented (shift=%d).\n",shift);
326 infilename = c_infilename[components++] = argv[i]+2;
332 outfilename = argv[i]+2;
338 if ( sscanf(argv[i],"-v%d",&verbose) != 1 ) {
343 /* Error level - if 0 then means loss-less mode */
346 if ( sscanf(argv[i]+2,"%d",&NEAR) != 1 ) {
355 /* Threshold Levels */
363 if ( sscanf(argv[i]+3,"%d",&T1) != 1 ) {
369 if ( sscanf(argv[i]+3,"%d",&T2) != 1 ) {
375 if ( sscanf(argv[i]+3,"%d",&T3) != 1 ) {
392 infilename = c_infilename[components++] = argv[i];
399 verbose = 1; /* at least the banner will show */
401 /* check that color mode is valid and pick color mode string */
402 switch ( color_mode ) {
404 color_mode_string = plane_int_string;
408 color_mode_string = line_int_string;
409 if (components>1) multi=1;
412 color_mode_string = pixel_int_string;
414 fprintf(stderr,"ERROR: specified more than 1 input file in pixel interleaved mode\n");
419 fprintf(stderr,"ERROR: Invalid color mode %d\n",color_mode);
425 /* Assign file pointers to in files */
426 if ( (infilename == NULL) && (multi==0 || components<1) ) {
431 if ( strcmp(infilename,"-") == 0 )
435 if ( (in=fopen(infilename,"rb")) == NULL ) {
441 for (i=0;i<components;i++)
442 if ( (c_in[i]=fopen(c_infilename[i],"rb")) == NULL ) {
443 perror(c_infilename[i]);
451 /* Assigns pointers to out files */
452 if ( outfilename == NULL ) {
457 if ( strcmp(outfilename,"-") == 0 ) {
461 else if ( (out=fopen(outfilename,"wb")) == NULL ) {
469 fprintf(msgfile,"%s\n",banner);
472 #define LESS_CONTEXTS 1
475 fprintf(msgfile,"Number of contexts (non-run): %d regular + %d EOR = %d\n",CONTEXTS-LESS_CONTEXTS,EOR_CONTEXTS,TOT_CONTEXTS-LESS_CONTEXTS);
477 /* Read image headers*/
479 if ( read_header_6(in, &columns, &rows, &alpha0, &components) != 0 )
480 error("Could not read image header. Must be PPM or PGM file.\n");
481 /* Single component => PLANE_INT */
482 if ( (color_mode==LINE_INT || color_mode==PIXEL_INT) && components==1) {
484 fprintf(msgfile,"Single component received: Color mode changed to PLANE INTERLEAVED\n");
486 color_mode=PLANE_INT;
487 color_mode_string = plane_int_string;
489 c_columns[0]=columns;
495 for (i=0;i<components;i++) {
496 if (read_header_5(c_in[i], &(c_columns[i]), &(c_rows[i]), &alpha0) != 0 )
497 error("ERROR: Could not read image header. Must be PGM file.\n");
499 common_rows=c_rows[0];
502 else if ((alpha0!=common_alpha)) {
503 fprintf(stderr,"\nERROR: All components must have same maximal value\n");
511 if ( alpha0 != alpha ) {
512 fprintf(stderr, "Sorry, this version has been optimized for alphabet size = %d, got %d\n",alpha,alpha0);
516 alpha = alpha0+1; /* number read from file header is alpha-1 */
517 ceil_half_alpha = (alpha+1)/2;
522 /* check that alpha is a power of 2 */
523 for ( alpha0=alpha, i=-1; alpha0; alpha0>>=1, i++);
524 if ( alpha != (1<<i) ) {
525 fprintf(stderr, "Sorry, this version has been optimized for alphabet size = power of 2, got %d\n",alpha);
530 /* Check for 16 or 8 bit mode */
531 if (alpha <= MAXA16 && alpha > MAXA8)
536 else if (alpha <= MAXA8 && alpha >= 1)
542 fprintf(stderr,"Got alpha = %d\n",alpha);
543 error("Bad value for alpha. Sorry...\n");
547 /* print out parameters */
550 fprintf(msgfile,"Input file: %s\nOutput file: %s\n",infilename,outfilename);
552 fprintf(msgfile,"Input files: ");
553 for (i=0;i<components;i++)
554 fprintf(msgfile," %s ",c_infilename[i]);
555 fprintf(msgfile,"\nOutput file: %s\n",outfilename);
559 fprintf(msgfile,"Image: cols=%d rows=%d alpha=%d comp=%d mode=%d (%s)",
560 columns, rows, alpha, components,
561 color_mode, color_mode_string);
563 fprintf(msgfile,"Image: cols=");
564 for (i=0;i<components;i++)
565 fprintf(msgfile," %d",c_columns[i]);
566 fprintf(msgfile," rows=");
567 for (i=0;i<components;i++)
568 fprintf(msgfile," %d",c_rows[i]);
569 fprintf(msgfile," alpha=%d comp=%d mode=%d (%s)",
570 alpha, components, color_mode,
574 fprintf(msgfile,"\n");
578 /* compute auxiliary parameters for near-lossless (globals) */
581 qbeta = (alpha + 2*NEAR + quant-1 )/quant;
583 ceil_half_qbeta = (qbeta+1)/2;
586 fprintf(msgfile,"Near-lossless mode: NEAR = %d beta = %d qbeta = %d\n",NEAR,beta,qbeta);
590 /* compute bits per sample for input symbols */
591 for ( bpp=1; (1L<<bpp)<alpha; bpp++ );
593 /* check if alpha is a power of 2: */
594 if ( alpha != (1<<bpp) )
595 need_lse = 1; /* if not, MAXVAL will be non-default, and
596 we'll need to specify it in an LSE marker */
599 /* compute bits per sample for unencoded prediction errors */
601 for ( qbpp=1; (1L<<qbpp)<qbeta; qbpp++ );
606 if ( bpp < 2 ) bpp = 2;
608 /* limit for unary part of Golomb code */
610 limit = 2*(bpp + 8) - qbpp -1;
612 limit = 4*bpp - qbpp - 1;
615 /* check for smallest subsampled file and compute the sampling */
616 if ((components>1) && (multi)) {
617 min_size_columns=c_columns[components-1];
618 min_size_rows=c_rows[components-1];
619 for (i=0;i<components-1;i++) {
620 if (c_columns[i]<min_size_columns)
621 min_size_columns=c_columns[i];
622 if (c_rows[i]<min_size_rows)
623 min_size_rows=c_rows[i];
626 for (i=0;i<components;i++) {
627 samplingx[i]=c_columns[i]/min_size_columns;
628 samplingy[i]=c_rows[i]/min_size_rows;
629 if ((samplingx[i]>4) || ((c_columns[i]%min_size_columns)!=0)) {
630 fprintf(stderr,"\nImage sizes not compatible\n");
633 if ((samplingy[i]>4) || ((c_rows[i]%min_size_rows)!=0)) {
634 fprintf(stderr,"\nImage sizes not compatible\n");
639 min_size_columns=c_columns[0];
640 whose_max_size_columns=0;
641 min_size_rows=c_rows[0];
642 whose_max_size_rows=0;
644 for (i=1;i<components;i++) {
645 if (c_columns[i]>min_size_columns) {
646 whose_max_size_columns=i;
647 min_size_columns=c_columns[i];
649 if (c_rows[i]>min_size_rows) {
650 whose_max_size_rows=i;
651 min_size_rows=c_rows[i];
656 for (i=0;i<components;i++) samplingx[i] = samplingy[i] = 1;
659 /* Allocate memory pools. */
660 initbuffers(multi, components);
667 int main (int argc, char *argv[]) {
669 int n,n_c,n_r,my_i, number_of_scans, n_s, i;
670 double t0, t1, get_utime();
678 pixel *local_scanl0,*local_scanl1,*local_pscanline,*local_cscanline;
680 application_header = all_header = 0;
682 /* Parse the parameters, initialize */
683 initialize(argc, argv);
685 /* Start timer (must be AFTER initialize()) */
688 /* Compute the number of scans */
689 /* Multiple scans only for PLANE_INT in this implementation */
691 if (color_mode==PLANE_INT)
692 number_of_scans=components;
697 /* Write the frame header - allocate memory for jpegls header */
698 head_frame = (jpeg_ls_header *) safecalloc(1,sizeof(jpeg_ls_header));
699 for (n_s=0;n_s<number_of_scans;n_s++)
700 head_scan[n_s] = (jpeg_ls_header *) safecalloc(1,sizeof(jpeg_ls_header));
702 /* Assigns columns/rows to head_frame */
704 head_frame->columns=columns;
705 head_frame->rows=rows;
708 head_frame->columns=c_columns[whose_max_size_columns];
709 head_frame->rows=c_rows[whose_max_size_rows];
712 head_frame->alp=alpha;
713 head_frame->comp=components;
715 /* Assign component id and samplingx/samplingy */
716 for (i=0;i<components;i++) {
717 head_frame->comp_ids[i]=i+1;
718 head_frame->samplingx[i]=samplingx[i];
719 head_frame->samplingy[i]=samplingy[i];
722 head_frame->NEAR=NEAR; /* Not needed, scan information */
723 head_frame->need_lse=need_lse; /* Not needed, for commpletness */
724 head_frame->color_mode=color_mode; /* Not needed, scan information */
725 head_frame->shift=shift; /* Not needed, scan information */
727 for (n_s=0;n_s<number_of_scans;n_s++) {
728 head_scan[n_s]->alp = alpha;
729 head_scan[n_s]->NEAR = NEAR;
730 head_scan[n_s]->T1 = T1;
731 head_scan[n_s]->T2 = T2;
732 head_scan[n_s]->T3 = T3;
733 head_scan[n_s]->RES = RESET;
734 head_scan[n_s]->shift = shift;
735 head_scan[n_s]->color_mode = color_mode;
739 if (color_mode==PLANE_INT) { /* One plane per scan */
740 for (n_s=0;n_s<number_of_scans;n_s++) {
741 head_scan[n_s]->comp=1;
742 head_scan[n_s]->comp_ids[0]=n_s+1;
746 for (n_s=0;n_s<number_of_scans;n_s++) {
747 head_scan[n_s]->comp=head_frame->comp;
748 for (n_c=0;n_c<head_frame->comp;n_c++)
749 head_scan[n_s]->comp_ids[n_c]=n_c+1;
754 all_header = write_marker(out, SOI);
756 /* Write the frame */
757 all_header += write_jpegls_frame(out, head_frame);
759 /* End of frame header writing */
762 if ((components>1) && (multi==0)) {
764 /* Received PPM file, allocate auxiliary buffers */
766 local_scanl0 = (pixel *)safecalloc(columns+LEFTMARGIN+RIGHTMARGIN,sizeof(pixel) );
767 local_scanl1 = (pixel *)safecalloc(columns+LEFTMARGIN+RIGHTMARGIN,sizeof(pixel) );
769 local_pscanline = local_scanl0 + LEFTMARGIN-1;
770 local_cscanline = local_scanl1 + LEFTMARGIN-1;
775 /* Go through each scan and process line by line */
776 for (n_s=0;n_s<number_of_scans;n_s++) {
778 /* process scans one by one */
781 /* The thresholds for the scan. Must re-do per scan is change. */
782 set_thresholds(alpha, NEAR, &T1, &T2, &T3);
783 for (i=0;i<number_of_scans;i++) {
784 head_scan[n_s]->T1=T1;
785 head_scan[n_s]->T2=T2;
786 head_scan[n_s]->T3=T3;
789 /* After the thresholds are set, write LSE marker if we have */
790 /* non-default parameters or if we need a mapping table */
792 all_header += write_jpegls_extmarker(out, head_scan[n_s], LSE_PARAMS, mappingtablefilename);
793 if ( need_table != 0 )
794 all_header += write_jpegls_extmarker(out, head_scan[n_s], LSE_MAPTABLE, mappingtablefilename);
797 /* If using restart markers, write the DRI header */
798 if ( need_restart != 0 )
800 head_scan[n_s]->restart_interval = restart_interval;
801 all_header += write_jpegls_restartmarker(out, head_scan[n_s]);
805 /* Print out parameters */
807 fprintf(msgfile,"Parameters: T1=%d T2=%d T3=%d RESET=%d limit=%d\n",T1, T2, T3,RESET,limit);
809 /* Prepare LUTs for context quantization */
810 /* Must re-do when Thresholds change */
814 /* prepare div/mul tables for near-lossless quantization */
815 prepare_qtables(alpha, NEAR);
817 /* Check for errors */
818 check_compatibility(head_frame, head_scan[0],0);
822 /* Restart Marker is reset after every scan */
825 /* Write the scan header */
826 all_header += write_jpegls_scan(out, head_scan[n_s]);
827 pos0 = ftell(out); /* position in output file, after header */
829 /* Initializations for each scan */
830 /* Start from 1st image row */
833 /* initialize stats arrays */
839 /* initialize run processing */
840 init_process_run(MAXRUN);
843 if (color_mode==LINE_INT) { /* line interleaved */
844 if (!multi) { /* Single file received */
845 /***********************************************************************/
846 /* Line interleaved mode with single file received */
847 /***********************************************************************/
852 while (++n <= rows) {
854 read_one_line(cscanline + components, components*columns, in);
856 tot_in += components*columns;
858 /* 'extend' the edges */
859 for (n_c=0;n_c<components;n_c++)
860 cscanline[-components+n_c] = cscanline[n_c]=pscanline[components+n_c];
862 for (n_c=0;n_c<components;n_c++) {
863 if (components > 1) {
864 for (my_i=0;my_i<columns+LEFTMARGIN+RIGHTMARGIN;my_i++){
865 local_cscanline[-1+my_i]=cscanline[-components+my_i*components+n_c];
866 local_pscanline[-1+my_i]=pscanline[-components+my_i*components+n_c];
870 local_cscanline=cscanline;
871 local_pscanline=pscanline;
874 /* process the lines */
875 lossless_doscanline(local_pscanline, local_cscanline, columns,n_c);
878 /* 'extend' the edges */
879 for (n_c=0;n_c<components;n_c++)
880 cscanline[components*(columns+1)+n_c]=cscanline[components*columns+n_c];
882 /* make the current scanline the previous one */
885 /* Insert restart markers if enabled */
888 /* Insert restart markers only after a restart interval */
889 if ((MCUs_counted % restart_interval) == 0)
892 write_marker(out, (RSTm + ((MCUs_counted / restart_interval)%8)));
901 while (++n <= rows) {
903 read_one_line(cscanline + components, components*columns, in);
905 tot_in += components*columns;
907 /* 'extend' the edges */
908 for (n_c=0;n_c<components;n_c++)
909 cscanline[-components+n_c] = cscanline[n_c]=pscanline[components+n_c];
911 for (n_c=0;n_c<components;n_c++) {
912 if (components > 1) {
913 for (my_i=0;my_i<columns+LEFTMARGIN+RIGHTMARGIN;my_i++){
914 local_cscanline[-1+my_i]=cscanline[-components+my_i*components+n_c];
915 local_pscanline[-1+my_i]=pscanline[-components+my_i*components+n_c];
919 local_cscanline=cscanline;
920 local_pscanline=pscanline;
923 /* process the lines */
924 lossy_doscanline(local_pscanline, local_cscanline, columns,n_c);
927 for (my_i=0;my_i<columns+LEFTMARGIN+RIGHTMARGIN;my_i++)
928 cscanline[-components+my_i*components+n_c]=local_cscanline[-1+my_i];
931 /* 'extend' the edges */
932 for (n_c=0;n_c<components;n_c++)
933 cscanline[components*(columns+1)+n_c]=cscanline[components*columns+n_c];
935 /* make the current scanline the previous one */
938 /* Insert restart markers if enabled */
941 /* Insert restart markers only after a restart interval */
942 if ((MCUs_counted % restart_interval) == 0)
945 write_marker(out, (RSTm + ((MCUs_counted / restart_interval)%8)));
952 else { /* Multiple files */
953 /* color_mode==LINE_INT and multi==1 */
955 /***********************************************************************/
956 /* Line interleaved mode with multiple files received */
957 /***********************************************************************/
963 while (n <= c_rows[whose_max_size_rows]) {
965 for (n_c=0;n_c<components;n_c++) {
966 for (n_r=0;n_r<samplingy[n_c];n_r++) {
968 read_one_line(c_cscanline[n_c] + 1, c_columns[n_c], c_in[n_c]);
970 tot_in += c_columns[n_c];
972 /* 'extend' the edges */
973 c_cscanline[n_c][-1]=c_cscanline[n_c][0]=c_pscanline[n_c][1];
975 /* process the lines */
976 lossless_doscanline(c_pscanline[n_c], c_cscanline[n_c], c_columns[n_c],n_c);
978 /* 'extend' the edges */
979 c_cscanline[n_c][c_columns[n_c]+1]=c_cscanline[n_c][c_columns[n_c]];
981 /* make the current scanline the previous one */
984 } /* End of loop for each file */
986 n+=samplingy[whose_max_size_rows];
988 /* Insert restart markers if enabled */
991 /* Insert restart markers only after a restart interval */
992 if ((MCUs_counted % restart_interval) == 0)
995 write_marker(out, (RSTm + ((MCUs_counted / restart_interval)%8)));
1000 } /* End while of LINE_INT with multiple input files */
1005 while (n <= c_rows[whose_max_size_rows]) {
1007 for (n_c=0;n_c<components;n_c++) {
1008 for (n_r=0;n_r<samplingy[n_c];n_r++) {
1010 read_one_line(c_cscanline[n_c] + 1, c_columns[n_c], c_in[n_c]);
1012 tot_in += c_columns[n_c];
1014 /* 'extend' the edges */
1015 c_cscanline[n_c][-1]=c_cscanline[n_c][0]=c_pscanline[n_c][1];
1017 /* process the lines */
1018 lossy_doscanline(c_pscanline[n_c], c_cscanline[n_c], c_columns[n_c],n_c);
1020 /* 'extend' the edges */
1021 c_cscanline[n_c][c_columns[n_c]+1]=c_cscanline[n_c][c_columns[n_c]];
1023 /* make the current scanline the previous one */
1026 } /* End of loop for each file */
1028 n+=samplingy[whose_max_size_rows];
1030 /* Insert restart markers if enabled */
1033 /* Insert restart markers only after a restart interval */
1034 if ((MCUs_counted % restart_interval) == 0)
1037 write_marker(out, (RSTm + ((MCUs_counted / restart_interval)%8)));
1042 } /* End while of LINE_INT with multiple input files */
1044 } /* Closes the else, LINE_INT and multi=1 */
1046 } /* Closes part for color_mode=LINE_INT */
1048 if (color_mode==PIXEL_INT) {
1049 /***********************************************************************/
1050 /* Pixel interleaved mode with single file received */
1051 /***********************************************************************/
1056 while (++n <= rows) {
1058 read_one_line(cscanline+components, components*columns, in);
1060 tot_in += components*columns;
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];
1066 /* process the lines */
1067 lossless_doscanline_pixel(pscanline, cscanline, components*columns);
1069 /* 'extend' the edges */
1070 for (n_c=0;n_c<components;n_c++)
1071 cscanline[components*(columns+1)+n_c] = cscanline[components*columns+n_c];
1073 /* make the current scanline the previous one */
1076 /* Insert restart markers if enabled */
1079 /* Insert restart markers only after a restart interval */
1080 if ((MCUs_counted % restart_interval) == 0)
1083 write_marker(out, (RSTm + ((MCUs_counted / restart_interval)%8)));
1092 while (++n <= rows) {
1094 read_one_line(cscanline+components, components*columns, in);
1096 tot_in += components*columns;
1098 /* 'extend' the edges */
1099 for (n_c=0;n_c<components;n_c++)
1100 cscanline[-components+n_c]=cscanline[n_c]=pscanline[components+n_c];
1102 /* process the lines */
1103 lossy_doscanline_pixel(pscanline, cscanline, components*columns);
1105 /* 'extend' the edges */
1106 for (n_c=0;n_c<components;n_c++)
1107 cscanline[components*(columns+1)+n_c] = cscanline[components*columns+n_c];
1109 /* make the current scanline the previous one */
1112 /* Insert restart markers if enabled */
1115 /* Insert restart markers only after a restart interval */
1116 if ((MCUs_counted % restart_interval) == 0)
1119 write_marker(out, (RSTm + ((MCUs_counted / restart_interval)%8)));
1125 } /* Closes if PIXEL_INT */
1126 else { /* NON PIXEL_INT */
1127 /***********************************************************************/
1128 /* Plane interleaved mode */
1129 /***********************************************************************/
1134 while (++n <= c_rows[n_s]) {
1136 temp_columns = c_columns[n_s];
1138 read_one_line(c_cscanline[n_s]+1, temp_columns, c_in[n_s]);
1140 tot_in += temp_columns;
1142 /* 'extend' the edges */
1143 c_cscanline[n_s][-1]=c_cscanline[n_s][0]=c_pscanline[n_s][1];
1145 /* process the lines */
1146 lossless_doscanline(c_pscanline[n_s], c_cscanline[n_s], temp_columns, n_s);
1148 /* 'extend' the edges */
1149 c_cscanline[n_s][temp_columns+1] = c_cscanline[n_s][temp_columns];
1151 /* make the current scanline the previous one */
1154 /* Insert restart markers if enabled */
1157 /* Insert restart markers only after a restart interval */
1158 if ((MCUs_counted % restart_interval) == 0)
1161 write_marker(out, (RSTm + ((MCUs_counted / restart_interval)%8)));
1171 while (++n <= c_rows[n_s]) {
1173 temp_columns = c_columns[n_s];
1175 read_one_line(c_cscanline[n_s]+1, temp_columns, c_in[n_s]);
1177 tot_in += temp_columns;
1179 /* 'extend' the edges */
1180 c_cscanline[n_s][-1]=c_cscanline[n_s][0]=c_pscanline[n_s][1];
1182 /* process the lines */
1183 lossy_doscanline(c_pscanline[n_s], c_cscanline[n_s], temp_columns,n_s);
1185 /* 'extend' the edges */
1186 c_cscanline[n_s][temp_columns+1] = c_cscanline[n_s][temp_columns];
1188 /* make the current scanline the previous one */
1191 /* Insert restart markers if enabled */
1194 /* Insert restart markers only after a restart interval */
1195 if ((MCUs_counted % restart_interval) == 0)
1198 write_marker(out, (RSTm + ((MCUs_counted / restart_interval)%8)));
1205 } /* End for each component in PLANE_INT */
1207 } /* End for non LINE_INT */
1210 } /* End of loop on scans */
1212 all_header += write_marker(out, EOI);
1215 close_process_run();
1216 pos1= closebuffers(multi);
1218 /* total bytes out, including JPEG-LS header, but not
1219 application-specific header bytes */
1220 /* tot_out = (pos1-all_header)*8; */
1226 fprintf(msgfile, "Used the mapping table from file : %s\n",mappingtablefilename);
1229 fprintf(msgfile, "Used restart markers with restart interval : %i\n", restart_interval);
1232 fprintf(msgfile,"Marker segment bytes: %ld\n",all_header);
1234 fprintf(msgfile,"Total bits out: %ld Symbols in: %ld %5.3lf bps (%5.3lf : 1)\n",
1236 tot_in,tot_out/(double)tot_in,
1237 (log((double)alpha)/log(2.0))*tot_in/tot_out);
1238 fprintf(msgfile,"Time = %1.3lf secs : %1.0lf KSymbols/sec\n",t1-t0,
1239 (tot_in)/(1024*(t1-t0)));
1247 /* Message to show how to use program */
1250 fprintf(stderr,"%s\n",banner);
1251 fprintf(stderr,"Usage: %s [flags] infile1 [infile2,infile3,...] [-ooutfile]\n\
1252 infile1 : Input file: must be in PGM or PPM format\n\
1253 infile2,...: Additional input files for \"plane interleaved\"\n\
1254 or \"line interleaved\" modes. Must be in PGM (P5) format.\n\
1256 -i<infile> : Alternate input specification, use -i- for stdin.\n\
1257 -o<outfile>: Output specification, use -o- for stdout (default=%s).\n\
1258 -Ta<num>, -Tb<num>, -Tc<num>: thresholds for context quantization (a.k.a.\n\
1259 T1,T2,T3; must have Ta<=Tb<=Tc<=maxs; defaults depend on alphabet\n\
1260 size and lossless/near-lossless mode; see standard specification).\n\
1261 -r<num> : Reset interval for statistics (standard default=%d).\n\
1262 ", "locoe", OUTFILE COMPSUFFIX,DEFAULT_RESET);
1264 -c<num> : Mode for multi-component images (program default=%d):\n\
1265 %d:%s %d:%s %d:%s.\n",
1267 PLANE_INT, "plane-interleaved",
1268 LINE_INT, "line-interleaved",
1269 PIXEL_INT, "sample-interleaved"
1273 -e<error> : Max allowed loss per symbol (default = %d).\n",
1277 -m<table> : Use mapping table where <table> is a file in the format:\n\
1278 1st byte of <table> is the Table ID,\n\
1279 2nd byte of <table> is the Width of each table entry (in bytes),\n\
1280 3rd - 6th byte of <table> is the Max Table Index Value specified\n\
1281 as an integer (4 bytes),\n\
1282 7th byte and on are the table entries.\n");
1284 -t<num> : Use Restart Markers where <num> is the restart interval \n\
1285 (ie. number of MCU's between restart markers).\n");
1288 -h : Print this help.\n");
1290 *** No spaces allowed between a flag and its argument.\n\
1291 *** Use -Ta,-Tb,-Tc,-r only if you know what you are doing!\n\
1297 /* Print out message for a bad flag */
1300 fprintf(stderr,"Bad flag %s\n",s);
1307 /* Functions that read the PGM header */
1309 #define HEADER_MAXLINE 256
1311 int read_header_6(FILE *fin, int *widthp, int *heightp, int *maxvalp, int *comp)
1313 char line[HEADER_MAXLINE];
1314 int cols,rows,maxval;
1316 if ( nextline(line, fin) != 0 )
1319 if (strncmp(line,"P5",2)==0) *comp=1;
1320 else if (strncmp(line,"P6",2)==0) *comp=3;
1321 else if (strncmp(line,"P7",2)==0) *comp=4;
1324 if ( nextline(line, fin) != 0 )
1327 if ( sscanf(line,"%d %d",&cols,&rows) != 2 )
1330 if ( nextline(line, fin) != 0 )
1333 if ( sscanf(line,"%d",&maxval) != 1 )
1345 int read_header_5(FILE *fin, int *widthp, int *heightp, int *maxvalp)
1347 char line[HEADER_MAXLINE];
1348 int cols,rows,maxval;
1350 if ( nextline(line, fin) != 0 )
1353 if (strncmp(line,"P5",2)!=0)
1356 if ( nextline(line, fin) != 0 )
1359 if ( sscanf(line,"%d %d",&cols,&rows) != 2 )
1362 if ( nextline(line, fin) != 0 )
1365 if ( sscanf(line,"%d",&maxval) != 1 )
1377 /* Used to read in header lines of PGM/PPM files */
1378 int nextline(char *line, FILE *fp)
1383 p = fgets(line, HEADER_MAXLINE, fp);
1386 fprintf(stderr,"%s",line);
1389 } while ( p != NULL && *p == '#' );