Ejemplo n.º 1
0
        // Decompression startup: read start of JPEG datastream to see what's there.
        // Need only initialize JPEG object and supply a data source before calling.
        //
        // This routine will read as far as the first SOS marker (ie, actual start of
        // compressed data), and will save all tables and parameters in the JPEG
        // object. It will also initialize the decompression parameters to default
        // values, and finally return JPEG_HEADER_OK. On return, the application may
        // adjust the decompression parameters and then call jpeg_start_decompress.
        // (Or, if the application only wanted to determine the image parameters,
        // the data need not be decompressed. In that case, call jpeg_abort or
        // jpeg_destroy to release any temporary space.)
        // If an abbreviated (tables only) datastream is presented, the routine will
        // return JPEG_HEADER_TABLES_ONLY upon reaching EOI. The application may then
        // re-use the JPEG object to read the abbreviated image datastream(s).
        // It is unnecessary (but OK) to call jpeg_abort in this case.
        // The JPEG_SUSPENDED return code only occurs if the data source module
        // requests suspension of the decompressor. In this case the application
        // should load more source data and then re-call jpeg_read_header to resume
        // processing.
        // If a non-suspending data source is used and require_image is true, then the
        // return code need not be inspected since only JPEG_HEADER_OK is possible.
        //
        // This routine is now just a front end to jpeg_consume_input, with some
        // extra error checking.
        public static CONSUME_INPUT jpeg_read_header(jpeg_decompress cinfo, bool require_image)
        {
            if (cinfo.global_state != STATE.DSTART && cinfo.global_state != STATE.DINHEADER)
            {
                ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_BAD_STATE, cinfo.global_state);
            }

            CONSUME_INPUT retcode = jpeg_consume_input(cinfo);

            switch (retcode)
            {
            case CONSUME_INPUT.JPEG_REACHED_SOS: return(CONSUME_INPUT.JPEG_HEADER_OK);

            case CONSUME_INPUT.JPEG_REACHED_EOI:
                if (require_image)
                {
                    ERREXIT(cinfo, J_MESSAGE_CODE.JERR_NO_IMAGE);                                       // Complain if application wanted an image
                }
                // Reset to start state; it would be safer to require the application to
                // call jpeg_abort, but we can't change it now for compatibility reasons.
                // A side effect is to free any temporary memory (there shouldn't be any).
                jpeg_abort(cinfo);                         // sets state=DSTART
                return(CONSUME_INPUT.JPEG_HEADER_TABLES_ONLY);
            }

            return(retcode);
        }
Ejemplo n.º 2
0
		const int CTX_POSTPONED_ROW=2;		// feeding postponed row group
#endif
		// Initialize for a processing pass.
		static void start_pass_d_main(jpeg_decompress cinfo, J_BUF_MODE pass_mode)
		{
			my_d_main_controller main=(my_d_main_controller)cinfo.main;

			switch(pass_mode)
			{
				case J_BUF_MODE.JBUF_PASS_THRU:
#if UPSCALING_CONTEXT
					if(cinfo.upsample.need_context_rows)
					{
						main.process_data=process_data_context_d_main;
						main.context_state=CTX_PREPARE_FOR_IMCU;
						main.iMCU_row_ctr=0;
					}
					else
#endif
						main.process_data=process_data_simple_d_main; // Simple case with no context needed
					main.buffer_full=false;	// Mark buffer empty
					main.rowgroup_ctr=0;
					break;
#if QUANT_2PASS_SUPPORTED
				case J_BUF_MODE.JBUF_CRANK_DEST: main.process_data=process_data_crank_post_d_main; break; // For last pass of 2-pass quantization, just crank the postprocessor
#endif
				default: ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_BUFFER_MODE); break;
			}
		}
Ejemplo n.º 3
0
        // *************** YCbCr -> RGB conversion: most common case *************

        // YCbCr is defined per CCIR 601-1, except that Cb and Cr are
        // normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5.
        // The conversion equations to be implemented are therefore
        //	R = Y				 + 1.40200 * Cr
        //	G = Y - 0.34414 * Cb - 0.71414 * Cr
        //	B = Y + 1.77200 * Cb
        // where Cb and Cr represent the incoming values less CENTERJSAMPLE.
        // (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.)
        //
        // To avoid floating-point arithmetic, we represent the fractional constants
        // as integers scaled up by 2^16 (about 4 digits precision); we have to divide
        // the products by 2^16, with appropriate rounding, to get the correct answer.
        // Notice that Y, being an integral input, does not contribute any fraction
        // so it need not participate in the rounding.
        //
        // For even more speed, we avoid doing any multiplications in the inner loop
        // by precalculating the constants times Cb and Cr for all possible values.
        // For 8-bit samples this is very reasonable (only 256 entries per table);
        // for 12-bit samples it is still acceptable. It's not very reasonable for
        // 16-bit samples, but if you want lossless storage you shouldn't be changing
        // colorspace anyway.
        // The Cr=>R and Cb=>B values can be rounded to integers in advance; the
        // values for the G calculation are left scaled up, since we must add them
        // together before rounding.

        // Initialize tables for YCC->RGB colorspace conversion.
        static void build_ycc_rgb_table(jpeg_decompress cinfo)
        {
            my_color_deconverter cconvert = (my_color_deconverter)cinfo.cconvert;

            try
            {
                cconvert.Cr_r_tab = new int[MAXJSAMPLE + 1];
                cconvert.Cb_b_tab = new int[MAXJSAMPLE + 1];
                cconvert.Cr_g_tab = new int[MAXJSAMPLE + 1];
                cconvert.Cb_g_tab = new int[MAXJSAMPLE + 1];
            }
            catch
            {
                ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_OUT_OF_MEMORY, 4);
            }

            for (int i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++)
            {
                // i is the actual input pixel value, in the range 0..MAXJSAMPLE
                // The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE
                // Cr=>R value is nearest int to 1.40200 * x
                cconvert.Cr_r_tab[i] = (int)((FIX_140200 * x + ONE_HALF) >> SCALEBITS);
                // Cb=>B value is nearest int to 1.77200 * x
                cconvert.Cb_b_tab[i] = (int)((FIX_177200 * x + ONE_HALF) >> SCALEBITS);
                // Cr=>G value is scaled-up -0.71414 * x
                cconvert.Cr_g_tab[i] = (-FIX_071414) * x;
                // Cb=>G value is scaled-up -0.34414 * x
                // We also add in ONE_HALF so that need not do it in inner loop
                cconvert.Cb_g_tab[i] = (-FIX_034414) * x + ONE_HALF;
            }
        }
Ejemplo n.º 4
0
        // Convert some rows of samples to the output colorspace.
        //
        // Note that we change from noninterleaved, one-plane-per-component format
        // to interleaved-pixel format. The output buffer is therefore three times
        // as wide as the input buffer.
        // A starting row offset is provided only for the input buffer. The caller
        // can easily adjust the passed output_buf value to accommodate any row
        // offset required on that side.
#if !USE_UNSAFE_STUFF
        static void ycc_rgb_convert(jpeg_decompress cinfo, byte[][][] input_buf, uint input_row, byte[][] output_buf, uint output_row, int num_rows)
        {
            my_color_deconverter cconvert = (my_color_deconverter)cinfo.cconvert;
            uint num_cols = cinfo.output_width;

            int[] Crrtab = cconvert.Cr_r_tab;
            int[] Cbbtab = cconvert.Cb_b_tab;
            int[] Crgtab = cconvert.Cr_g_tab;
            int[] Cbgtab = cconvert.Cb_g_tab;

            while (--num_rows >= 0)
            {
                byte[] inptr0 = input_buf[0][input_row];
                byte[] inptr1 = input_buf[1][input_row];
                byte[] inptr2 = input_buf[2][input_row];
                input_row++;
                byte[] outptr = output_buf[output_row++];
                for (uint col = 0, outptr_ind = 0; col < num_cols; col++, outptr_ind += RGB_PIXELSIZE)
                {
                    int y  = inptr0[col];
                    int cb = inptr1[col];
                    int cr = inptr2[col];

                    // Range-limiting is essential due to noise introduced by DCT losses.
                    int tmp = y + Crrtab[cr];
                    outptr[outptr_ind + RGB_RED] = (byte)(tmp >= MAXJSAMPLE?MAXJSAMPLE:(tmp < 0?0:tmp));
                    tmp = y + ((int)((Cbgtab[cb] + Crgtab[cr]) >> SCALEBITS));
                    outptr[outptr_ind + RGB_GREEN] = (byte)(tmp >= MAXJSAMPLE?MAXJSAMPLE:(tmp < 0?0:tmp));
                    tmp = y + Cbbtab[cb];
                    outptr[outptr_ind + RGB_BLUE] = (byte)(tmp >= MAXJSAMPLE?MAXJSAMPLE:(tmp < 0?0:tmp));
                }
            }
        }
Ejemplo n.º 5
0
		// Determine whether merged upsample/color conversion should be used.
		// CRUCIAL: this must match the actual capabilities of jdmerge.cs!
		static bool use_merged_upsample(jpeg_decompress cinfo)
		{
#if UPSAMPLE_MERGING_SUPPORTED
			// Merging is the equivalent of plain box-filter upsampling
			if(cinfo.do_fancy_upsampling||cinfo.CCIR601_sampling) return false;

			// jdmerge.cs only supports YCC=>RGB color conversion
			if(cinfo.jpeg_color_space!=J_COLOR_SPACE.JCS_YCbCr||cinfo.num_components!=3||
				cinfo.out_color_space!=J_COLOR_SPACE.JCS_RGB||cinfo.out_color_components!=RGB_PIXELSIZE) return false;

			// and it only handles 2h1v or 2h2v sampling ratios
			if(cinfo.comp_info[0].h_samp_factor!=2||cinfo.comp_info[1].h_samp_factor!=1||
				cinfo.comp_info[2].h_samp_factor!=1||cinfo.comp_info[0].v_samp_factor>2||
				cinfo.comp_info[1].v_samp_factor!=1||cinfo.comp_info[2].v_samp_factor!=1) return false;

			// furthermore, it doesn't work if each component has been processed differently
			if(cinfo.comp_info[0].DCT_scaled_size!=cinfo.min_DCT_scaled_size||
				cinfo.comp_info[1].DCT_scaled_size!=cinfo.min_DCT_scaled_size||
				cinfo.comp_info[2].DCT_scaled_size!=cinfo.min_DCT_scaled_size) return false;

			// ??? also need to test for upsample-time rescaling, when & if supported
			return true; // by golly, it'll work... 
#else
			return false;
#endif
		}
Ejemplo n.º 6
0
        // Process some data.
        // This handles the simple case where no context is required.
        static void process_data_simple_d_main(jpeg_decompress cinfo, byte[][] output_buf, ref uint out_row_ctr, uint out_rows_avail)
        {
            my_d_main_controller main = (my_d_main_controller)cinfo.main;
            uint rowgroups_avail;

            // Read input data if we haven't filled the main buffer yet
            if (!main.buffer_full)
            {
                if (cinfo.coef.decompress_data(cinfo, main.buffer) == CONSUME_INPUT.JPEG_SUSPENDED)
                {
                    return;                            // suspension forced, can do nothing more
                }
                main.buffer_full = true;               // OK, we have an iMCU row to work with
            }

            // There are always min_codec_data_unit row groups in an iMCU row.
            rowgroups_avail = (uint)cinfo.min_DCT_scaled_size;
            // Note: at the bottom of the image, we may pass extra garbage row groups
            // to the postprocessor. The postprocessor has to check for bottom
            // of image anyway (at row resolution), so no point in us doing it too.

            // Feed the postprocessor
            cinfo.post.post_process_data(cinfo, main.buffer, ref main.rowgroup_ctr, rowgroups_avail, output_buf, 0, ref out_row_ctr, out_rows_avail);

            // Has postprocessor consumed all the data yet? If so, mark buffer empty
            if (main.rowgroup_ctr >= rowgroups_avail)
            {
                main.buffer_full  = false;
                main.rowgroup_ctr = 0;
            }
        }
Ejemplo n.º 7
0
        // MCU decoding for DC successive approximation refinement scan.
        static bool decode_mcu_DC_refine_arith(jpeg_decompress cinfo, short[][] MCU_data)
        {
            arith_entropy_decoder entropy = (arith_entropy_decoder)cinfo.coef;

            // Process restart marker if needed
            if (cinfo.restart_interval != 0)
            {
                if (entropy.restarts_to_go == 0)
                {
                    process_restart_arith(cinfo);
                }
                entropy.restarts_to_go--;
            }

            short p1 = (short)(1 << cinfo.Al);         // 1 in the bit position being coded

            // Outer loop handles each block in the MCU
            for (int blkn = 0; blkn < cinfo.blocks_in_MCU; blkn++)
            {
                byte st = 0;                    // use fixed probability estimation
                // Encoded data is simply the next bit of the two's-complement DC value
                if (arith_decode(cinfo, ref st) != 0)
                {
                    MCU_data[blkn][0] |= p1;
                }
            }

            return(true);
        }
Ejemplo n.º 8
0
        public const int SAVED_COEFS = 6;               // we save coef_bits[0..5]

        // Reset within-iMCU-row counters for a new row (input side)
        static void start_iMCU_row_d_coef(jpeg_decompress cinfo)
        {
            jpeg_lossy_d_codec lossyd = (jpeg_lossy_d_codec)cinfo.coef;
            d_coef_controller  coef   = (d_coef_controller)lossyd.coef_private;

            // In an interleaved scan, an MCU row is the same as an iMCU row.
            // In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows.
            // But at the bottom of the image, process only what's left.
            if (cinfo.comps_in_scan > 1)
            {
                coef.MCU_rows_per_iMCU_row = 1;
            }
            else
            {
                if (cinfo.input_iMCU_row < (cinfo.total_iMCU_rows - 1))
                {
                    coef.MCU_rows_per_iMCU_row = cinfo.cur_comp_info[0].v_samp_factor;
                }
                else
                {
                    coef.MCU_rows_per_iMCU_row = cinfo.cur_comp_info[0].last_row_height;
                }
            }

            coef.MCU_ctr         = 0;
            coef.MCU_vert_offset = 0;
        }
Ejemplo n.º 9
0
        // Process some data in the first pass of 2-pass quantization.
        static void post_process_prepass(jpeg_decompress cinfo, byte[][][] input_buf, ref uint in_row_group_ctr, uint in_row_groups_avail, byte[][] output_buf, uint ignore_me, ref uint out_row_ctr, uint out_rows_avail)
        {
            my_post_controller post = (my_post_controller)cinfo.post;

            // Reposition virtual buffer if at start of strip.
            if (post.next_row == 0)
            {
                post.buffer        = post.whole_image;
                post.buffer_offset = post.starting_row;
            }

            // Upsample some data (up to a strip height's worth).
            uint old_next_row = post.next_row;

            cinfo.upsample.upsample(cinfo, input_buf, ref in_row_group_ctr, in_row_groups_avail, post.buffer, post.buffer_offset, ref post.next_row, post.strip_height);

            // Allow quantizer to scan new data. No data is emitted,
            // but we advance out_row_ctr so outer loop can tell when we're done.
            if (post.next_row > old_next_row)
            {
                uint num_rows = post.next_row - old_next_row;
                cinfo.cquantize.color_quantize(cinfo, post.buffer, post.buffer_offset + old_next_row, null, 0, (int)num_rows);
                out_row_ctr += num_rows;
            }

            // Advance if we filled the strip.
            if (post.next_row >= post.strip_height)
            {
                post.starting_row += post.strip_height;
                post.next_row      = 0;
            }
        }
Ejemplo n.º 10
0
		// *************** YCbCr -> RGB conversion: most common case *************

		// YCbCr is defined per CCIR 601-1, except that Cb and Cr are
		// normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5.
		// The conversion equations to be implemented are therefore
		//	R = Y				 + 1.40200 * Cr
		//	G = Y - 0.34414 * Cb - 0.71414 * Cr
		//	B = Y + 1.77200 * Cb
		// where Cb and Cr represent the incoming values less CENTERJSAMPLE.
		// (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.)
		//
		// To avoid floating-point arithmetic, we represent the fractional constants
		// as integers scaled up by 2^16 (about 4 digits precision); we have to divide
		// the products by 2^16, with appropriate rounding, to get the correct answer.
		// Notice that Y, being an integral input, does not contribute any fraction
		// so it need not participate in the rounding.
		//
		// For even more speed, we avoid doing any multiplications in the inner loop
		// by precalculating the constants times Cb and Cr for all possible values.
		// For 8-bit samples this is very reasonable (only 256 entries per table);
		// for 12-bit samples it is still acceptable. It's not very reasonable for
		// 16-bit samples, but if you want lossless storage you shouldn't be changing
		// colorspace anyway.
		// The Cr=>R and Cb=>B values can be rounded to integers in advance; the
		// values for the G calculation are left scaled up, since we must add them
		// together before rounding.

		// Initialize tables for YCC->RGB colorspace conversion.
		static void build_ycc_rgb_table(jpeg_decompress cinfo)
		{
			my_color_deconverter cconvert=(my_color_deconverter)cinfo.cconvert;

			try
			{
				cconvert.Cr_r_tab=new int[MAXJSAMPLE+1];
				cconvert.Cb_b_tab=new int[MAXJSAMPLE+1];
				cconvert.Cr_g_tab=new int[MAXJSAMPLE+1];
				cconvert.Cb_g_tab=new int[MAXJSAMPLE+1];
			}
			catch
			{
				ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_OUT_OF_MEMORY, 4);
			}

			for(int i=0, x=-CENTERJSAMPLE; i<=MAXJSAMPLE; i++, x++)
			{
				// i is the actual input pixel value, in the range 0..MAXJSAMPLE
				// The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE
				// Cr=>R value is nearest int to 1.40200 * x
				cconvert.Cr_r_tab[i]=(int)((FIX_140200*x+ONE_HALF)>>SCALEBITS);
				// Cb=>B value is nearest int to 1.77200 * x
				cconvert.Cb_b_tab[i]=(int)((FIX_177200*x+ONE_HALF)>>SCALEBITS);
				// Cr=>G value is scaled-up -0.71414 * x
				cconvert.Cr_g_tab[i]=(-FIX_071414)*x;
				// Cb=>G value is scaled-up -0.34414 * x
				// We also add in ONE_HALF so that need not do it in inner loop
				cconvert.Cb_g_tab[i]=(-FIX_034414)*x+ONE_HALF;
			}
		}
Ejemplo n.º 11
0
        // Read some scanlines of data from the JPEG decompressor.
        //
        // The return value will be the number of lines actually read.
        // This may be less than the number requested in several cases,
        // including bottom of image, data source suspension, and operating
        // modes that emit multiple scanlines at a time.
        //
        // Note: we warn about excess calls to jpeg_read_scanlines() since
        // this likely signals an application programmer error. However,
        // an oversize buffer (max_lines > scanlines remaining) is not an error.
        public static uint jpeg_read_scanlines(jpeg_decompress cinfo, byte[][] scanlines, uint max_lines)
        {
            if (cinfo.global_state != STATE.DSCANNING)
            {
                ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_BAD_STATE, cinfo.global_state);
            }
            if (cinfo.output_scanline >= cinfo.output_height)
            {
                WARNMS(cinfo, J_MESSAGE_CODE.JWRN_TOO_MUCH_DATA);
                return(0);
            }

            // Call progress monitor hook if present
            if (cinfo.progress != null)
            {
                cinfo.progress.pass_counter = (int)cinfo.output_scanline;
                cinfo.progress.pass_limit   = (int)cinfo.output_height;
                cinfo.progress.progress_monitor(cinfo);
            }

            // Process some data
            uint row_ctr = 0;

            cinfo.main.process_data(cinfo, scanlines, ref row_ctr, max_lines);
            cinfo.output_scanline += row_ctr;
            return(row_ctr);
        }
Ejemplo n.º 12
0
        static void scaler_start_pass(jpeg_decompress cinfo)
        {
            jpeg_lossless_d_codec losslsd = (jpeg_lossless_d_codec)cinfo.coef;
            scaler scaler = (scaler)losslsd.scaler_private;

            // Downscale by the difference in the input vs. output precision. If the
            // output precision >= input precision, then do not downscale.
            int downscale = BITS_IN_JSAMPLE < cinfo.data_precision?cinfo.data_precision - BITS_IN_JSAMPLE:0;

            scaler.scale_factor = cinfo.Al - downscale;

            // Set scaler functions based on scale_factor (positive = left shift)
            if (scaler.scale_factor > 0)
            {
                losslsd.scaler_scale = simple_upscale;
            }
            else if (scaler.scale_factor < 0)
            {
                scaler.scale_factor  = -scaler.scale_factor;
                losslsd.scaler_scale = simple_downscale;
            }
            else
            {
                losslsd.scaler_scale = noscale;
            }
        }
Ejemplo n.º 13
0
        // Module initialization routine for the undifferencer.
        static void jinit_undifferencer(jpeg_decompress cinfo)
        {
            jpeg_lossless_d_codec losslsd = (jpeg_lossless_d_codec)cinfo.coef;

            losslsd.predict_start_pass      = start_pass_d_pred;
            losslsd.predict_process_restart = start_pass_d_pred;
        }
Ejemplo n.º 14
0
        // Initialize IDCT manager.
        static void jinit_inverse_dct(jpeg_decompress cinfo)
        {
            jpeg_lossy_d_codec lossyd = (jpeg_lossy_d_codec)cinfo.coef;
            idct_controller    idct   = null;

            try
            {
                idct = new idct_controller();
            }
            catch
            {
                ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_OUT_OF_MEMORY, 4);
            }

            lossyd.idct_private    = idct;
            lossyd.idct_start_pass = start_pass_idctmgr;

            for (int ci = 0; ci < cinfo.num_components; ci++)
            {
                jpeg_component_info compptr = cinfo.comp_info[ci];

                // Allocate and pre-zero a multiplier table for each component
                try
                {
                    compptr.dct_table = new int[DCTSIZE2];
                }
                catch
                {
                    ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_OUT_OF_MEMORY, 4);
                }

                // Mark multiplier table not yet set up for any method
                idct.cur_method[ci] = -1;
            }
        }
Ejemplo n.º 15
0
        // Initialize for an output processing pass.
        static void start_output_pass_lossy(jpeg_decompress cinfo)
        {
            jpeg_lossy_d_codec lossyd = (jpeg_lossy_d_codec)cinfo.coef;

            lossyd.idct_start_pass(cinfo);
            lossyd.coef_start_output_pass(cinfo);
        }
Ejemplo n.º 16
0
 static void noscale(jpeg_decompress cinfo, int[] diff_buf, byte[] output_buf, uint width)
 {
     for (uint xindex = 0; xindex < width; xindex++)
     {
         output_buf[xindex] = (byte)diff_buf[xindex];
     }
 }
Ejemplo n.º 17
0
		// Initialize for an output processing pass.
		static void start_output_pass_lossy(jpeg_decompress cinfo)
		{
			jpeg_lossy_d_codec lossyd=(jpeg_lossy_d_codec)cinfo.coef;

			lossyd.idct_start_pass(cinfo);
			lossyd.coef_start_output_pass(cinfo);
		}
Ejemplo n.º 18
0
        // Finish up after an output pass in buffered-image mode.
        //
        // Returns false if suspended. The return value need be inspected only if
        // a suspending data source is used.
        public static bool jpeg_finish_output(jpeg_decompress cinfo)
        {
            if ((cinfo.global_state == STATE.DSCANNING || cinfo.global_state == STATE.DRAW_OK) && cinfo.buffered_image)
            {
                // Terminate this pass.
                // We do not require the whole pass to have been completed.
                cinfo.master.finish_output_pass(cinfo);
                cinfo.global_state = STATE.DBUFPOST;
            }
            else if (cinfo.global_state != STATE.DBUFPOST)
            {
                // BUFPOST = repeat call after a suspension, anything else is error
                ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_BAD_STATE, cinfo.global_state);
            }

            // Read markers looking for SOS or EOI
            while (cinfo.input_scan_number <= cinfo.output_scan_number && !cinfo.inputctl.eoi_reached)
            {
                if (cinfo.inputctl.consume_input(cinfo) == CONSUME_INPUT.JPEG_SUSPENDED)
                {
                    return(false);                                                                                  // Suspend, come back later
                }
            }
            cinfo.global_state = STATE.DBUFIMAGE;
            return(true);
        }
Ejemplo n.º 19
0
        // Undifferencer for the first row in a scan or restart interval. The first
        // sample in the row is undifferenced using the special predictor constant
        // x=2^(P-Pt-1). The rest of the samples are undifferenced using the
        // 1-D horizontal predictor (1).
        static void jpeg_undifference_first_row(jpeg_decompress cinfo, int comp_index, int[] diff_buf, int[] prev_row, int[] undiff_buf, uint width)
        {
            jpeg_lossless_d_codec losslsd = (jpeg_lossless_d_codec)cinfo.coef;

            int Ra = (diff_buf[0] + (1 << (cinfo.data_precision - cinfo.Al - 1))) & 0xFFFF;

            undiff_buf[0] = Ra;

            for (uint xindex = 1; xindex < width; xindex++)
            {
                Ra = (diff_buf[xindex] + Ra) & 0xFFFF;
                undiff_buf[xindex] = Ra;
            }

            // Now that we have undifferenced the first row, we want to use the
            // undifferencer which corresponds to the predictor specified in the
            // scan header.
            switch (cinfo.Ss)
            {
            case 1: losslsd.predict_undifference[comp_index] = jpeg_undifference1; break;

            case 2: losslsd.predict_undifference[comp_index] = jpeg_undifference2; break;

            case 3: losslsd.predict_undifference[comp_index] = jpeg_undifference3; break;

            case 4: losslsd.predict_undifference[comp_index] = jpeg_undifference4; break;

            case 5: losslsd.predict_undifference[comp_index] = jpeg_undifference5; break;

            case 6: losslsd.predict_undifference[comp_index] = jpeg_undifference6; break;

            case 7: losslsd.predict_undifference[comp_index] = jpeg_undifference7; break;
            }
        }
Ejemplo n.º 20
0
        const int CTX_POSTPONED_ROW    = 2;             // feeding postponed row group
#endif
        // Initialize for a processing pass.
        static void start_pass_d_main(jpeg_decompress cinfo, J_BUF_MODE pass_mode)
        {
            my_d_main_controller main = (my_d_main_controller)cinfo.main;

            switch (pass_mode)
            {
            case J_BUF_MODE.JBUF_PASS_THRU:
#if UPSCALING_CONTEXT
                if (cinfo.upsample.need_context_rows)
                {
                    main.process_data  = process_data_context_d_main;
                    main.context_state = CTX_PREPARE_FOR_IMCU;
                    main.iMCU_row_ctr  = 0;
                }
                else
#endif
                main.process_data = process_data_simple_d_main; // Simple case with no context needed
                main.buffer_full  = false;                      // Mark buffer empty
                main.rowgroup_ctr = 0;
                break;

#if QUANT_2PASS_SUPPORTED
            case J_BUF_MODE.JBUF_CRANK_DEST: main.process_data = process_data_crank_post_d_main; break;                   // For last pass of 2-pass quantization, just crank the postprocessor
#endif
            default: ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_BUFFER_MODE); break;
            }
        }
Ejemplo n.º 21
0
		// Routines to process JPEG markers.
		//
		// Entry condition: JPEG marker itself has been read and its code saved
		//	in cinfo.unread_marker; input restart point is just after the marker.
		//
		// Exit: if return true, have read and processed any parameters, and have
		//	updated the restart point to point after the parameters.
		//	If return false, was forced to suspend before reaching end of
		//	marker parameters; restart point has not been moved. Same routine
		//	will be called again after application supplies more input data.
		//
		// This approach to suspension assumes that all of a marker's parameters
		// can fit into a single input bufferload. This should hold for "normal"
		// markers. Some COM/APPn markers might have large parameter segments
		// that might not fit. If we are simply dropping such a marker, we use
		// skip_input_data to get past it, and thereby put the problem on the
		// source manager's shoulders. If we are saving the marker's contents
		// into memory, we use a slightly different convention: when forced to
		// suspend, the marker processor updates the restart point to the end of
		// what it's consumed (ie, the end of the buffer) before returning false.
		// On resumption, cinfo.unread_marker still contains the marker code,
		// but the data source will point to the next chunk of marker data.
		// The marker processor must retain internal state to deal with this.
		//
		// Note that we don't bother to avoid duplicate trace messages if a
		// suspension occurs within marker parameters. Other side effects
		// require more care.

		// Process an SOI marker
		static bool get_soi(jpeg_decompress cinfo)
		{
			TRACEMS(cinfo, 1, J_MESSAGE_CODE.JTRC_SOI);

			if(cinfo.marker.saw_SOI) ERREXIT(cinfo, J_MESSAGE_CODE.JERR_SOI_DUPLICATE);

			// Reset all parameters that are defined to be reset by SOI
			for(int i=0; i<NUM_ARITH_TBLS; i++)
			{
				cinfo.arith_dc_L[i]=0;
				cinfo.arith_dc_U[i]=1;
				cinfo.arith_ac_K[i]=5;
			}
			cinfo.restart_interval=0;

			// Set initial assumptions for colorspace etc
			cinfo.jpeg_color_space=J_COLOR_SPACE.JCS_UNKNOWN;
			cinfo.CCIR601_sampling=false;	// Assume non-CCIR sampling???

			cinfo.saw_JFIF_marker=false;
			cinfo.JFIF_major_version=1;		// set default JFIF APP0 values
			cinfo.JFIF_minor_version=1;
			cinfo.density_unit=0;
			cinfo.X_density=1;
			cinfo.Y_density=1;
			cinfo.saw_Adobe_marker=false;
			cinfo.Adobe_transform=0;

			cinfo.marker.saw_SOI=true;

			return true;
		}
Ejemplo n.º 22
0
        // Save away a copy of the Q-table referenced by each component present
        // in the current scan, unless already saved during a prior scan.
        //
        // In a multiple-scan JPEG file, the encoder could assign different components
        // the same Q-table slot number, but change table definitions between scans
        // so that each component uses a different Q-table. (The IJG encoder is not
        // currently capable of doing this, but other encoders might.) Since we want
        // to be able to dequantize all the components at the end of the file, this
        // means that we have to save away the table actually used for each component.
        // We do this by copying the table at the start of the first scan containing
        // the component.
        // The JPEG spec prohibits the encoder from changing the contents of a Q-table
        // slot between scans of a component using that slot. If the encoder does so
        // anyway, this decoder will simply use the Q-table values that were current
        // at the start of the first scan for the component.
        //
        // The decompressor output side looks only at the saved quant tables,
        // not at the current Q-table slots.
        static void latch_quant_tables_lossy(jpeg_decompress cinfo)
        {
            for (int ci = 0; ci < cinfo.comps_in_scan; ci++)
            {
                jpeg_component_info compptr = cinfo.cur_comp_info[ci];
                // No work if we already saved Q-table for this component
                if (compptr.quant_table != null)
                {
                    continue;
                }

                // Make sure specified quantization table is present
                int qtblno = compptr.quant_tbl_no;
                if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS || cinfo.quant_tbl_ptrs[qtblno] == null)
                {
                    ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_NO_QUANT_TABLE, qtblno);
                }

                // OK, save away the quantization table
                JQUANT_TBL qtbl = new JQUANT_TBL();

                cinfo.quant_tbl_ptrs[qtblno].quantval.CopyTo(qtbl.quantval, 0);
                qtbl.sent_table = cinfo.quant_tbl_ptrs[qtblno].sent_table;

                compptr.quant_table = qtbl;
            }
        }
Ejemplo n.º 23
0
        // Initialize for a Huffman-compressed scan.
        static void start_pass_huff_decoder(jpeg_decompress cinfo)
        {
            jpeg_lossy_d_codec    lossyd  = (jpeg_lossy_d_codec)cinfo.coef;
            shuff_entropy_decoder entropy = (shuff_entropy_decoder)lossyd.entropy_private;

            // Check that the scan parameters Ss, Se, Ah/Al are OK for sequential JPEG.
            // This ought to be an error condition, but we make it a warning because
            // there are some baseline files out there with all zeroes in these bytes.
            if (cinfo.Ss != 0 || cinfo.Se != DCTSIZE2 - 1 || cinfo.Ah != 0 || cinfo.Al != 0)
            {
                WARNMS(cinfo, J_MESSAGE_CODE.JWRN_NOT_SEQUENTIAL);
            }

            for (int ci = 0; ci < cinfo.comps_in_scan; ci++)
            {
                jpeg_component_info compptr = cinfo.cur_comp_info[ci];
                int dctbl = compptr.dc_tbl_no;
                int actbl = compptr.ac_tbl_no;

                // Compute derived values for Huffman tables
                // We may do this more than once for a table, but it's not expensive
                jpeg_make_d_derived_tbl(cinfo, true, dctbl, ref entropy.dc_derived_tbls[dctbl]);
                jpeg_make_d_derived_tbl(cinfo, false, actbl, ref entropy.ac_derived_tbls[actbl]);

                // Initialize DC predictions to 0
                entropy.saved.last_dc_val[ci] = 0;
            }

            // Precalculate decoding info for each block in an MCU of this scan
            for (int blkn = 0; blkn < cinfo.blocks_in_MCU; blkn++)
            {
                int ci = cinfo.MCU_membership[blkn];
                jpeg_component_info compptr = cinfo.cur_comp_info[ci];

                // Precalculate which table to use for each block
                entropy.dc_cur_tbls[blkn] = entropy.dc_derived_tbls[compptr.dc_tbl_no];
                entropy.ac_cur_tbls[blkn] = entropy.ac_derived_tbls[compptr.ac_tbl_no];

                // Decide whether we really care about the coefficient values
                if (compptr.component_needed)
                {
                    entropy.dc_needed[blkn] = true;
                    // we don't need the ACs if producing a 1/8th-size image
                    entropy.ac_needed[blkn] = (compptr.DCT_scaled_size > 1);
                }
                else
                {
                    entropy.dc_needed[blkn] = entropy.ac_needed[blkn] = false;
                }
            }

            // Initialize bitread state variables
            entropy.bitstate.bits_left  = 0;
            entropy.bitstate.get_buffer = 0;           // unnecessary, but keeps Purify quiet
            entropy.insufficient_data   = false;

            // Initialize restart counter
            entropy.restarts_to_go = cinfo.restart_interval;
        }
Ejemplo n.º 24
0
        // Initialize for an input processing pass.
        static void start_input_pass_lossy(jpeg_decompress cinfo)
        {
            jpeg_lossy_d_codec lossyd = (jpeg_lossy_d_codec)cinfo.coef;

            latch_quant_tables_lossy(cinfo);
            lossyd.entropy_start_pass(cinfo);
            lossyd.coef_start_input_pass(cinfo);
        }
Ejemplo n.º 25
0
		// Compute output image dimensions and related values.
		static void calc_output_dimensions_lossy(jpeg_decompress cinfo)
		{
			// Hardwire it to "no scaling"
			cinfo.output_width=cinfo.image_width;
			cinfo.output_height=cinfo.image_height;
			// jdinput.cs has already initialized codec_data_unit to DCTSIZE,
			// and has computed unscaled downsampled_width and downsampled_height.
		}
Ejemplo n.º 26
0
		// Initialize for an input processing pass.
		static void start_input_pass_lossy(jpeg_decompress cinfo)
		{
			jpeg_lossy_d_codec lossyd=(jpeg_lossy_d_codec)cinfo.coef;

			latch_quant_tables_lossy(cinfo);
			lossyd.entropy_start_pass(cinfo);
			lossyd.coef_start_input_pass(cinfo);
		}
Ejemplo n.º 27
0
		static void simple_downscale(jpeg_decompress cinfo, int[] diff_buf, byte[] output_buf, uint width)
		{
			jpeg_lossless_d_codec losslsd=(jpeg_lossless_d_codec)cinfo.coef;
			scaler scaler=(scaler)losslsd.scaler_private;

			int scale_factor=scaler.scale_factor;
			for(uint xindex=0; xindex<width; xindex++) output_buf[xindex]=(byte)(diff_buf[xindex]>>scale_factor);
		}
Ejemplo n.º 28
0
 // Compute output image dimensions and related values.
 static void calc_output_dimensions_lossy(jpeg_decompress cinfo)
 {
     // Hardwire it to "no scaling"
     cinfo.output_width  = cinfo.image_width;
     cinfo.output_height = cinfo.image_height;
     // jdinput.cs has already initialized codec_data_unit to DCTSIZE,
     // and has computed unscaled downsampled_width and downsampled_height.
 }
Ejemplo n.º 29
0
		// Initialize for an input processing pass.
		static void start_input_pass_ls(jpeg_decompress cinfo)
		{
			jpeg_lossless_d_codec losslsd=(jpeg_lossless_d_codec)cinfo.coef;

			losslsd.entropy_start_pass(cinfo);
			losslsd.predict_start_pass(cinfo);
			losslsd.scaler_start_pass(cinfo);
			losslsd.diff_start_input_pass(cinfo);
		}
Ejemplo n.º 30
0
        // Initialize for an input processing pass.
        static void start_input_pass_ls(jpeg_decompress cinfo)
        {
            jpeg_lossless_d_codec losslsd = (jpeg_lossless_d_codec)cinfo.coef;

            losslsd.entropy_start_pass(cinfo);
            losslsd.predict_start_pass(cinfo);
            losslsd.scaler_start_pass(cinfo);
            losslsd.diff_start_input_pass(cinfo);
        }
Ejemplo n.º 31
0
 // Have we finished reading the input file?
 public static bool jpeg_input_complete(jpeg_decompress cinfo)
 {
     // Check for valid jpeg object
     if (cinfo.global_state < STATE.DSTART || cinfo.global_state > STATE.DSTOPPING)
     {
         ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_BAD_STATE, cinfo.global_state);
     }
     return(cinfo.inputctl.eoi_reached);
 }
Ejemplo n.º 32
0
 // Is there more than one scan?
 public static bool jpeg_has_multiple_scans(jpeg_decompress cinfo)
 {
     // Only valid after jpeg_read_header completes
     if (cinfo.global_state < STATE.DREADY || cinfo.global_state > STATE.DSTOPPING)
     {
         ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_BAD_STATE, cinfo.global_state);
     }
     return(cinfo.inputctl.has_multiple_scans);
 }
Ejemplo n.º 33
0
        // Finish up at end of an output pass.
        static void finish_output_pass(jpeg_decompress cinfo)
        {
            my_decomp_master master = (my_decomp_master)cinfo.master;

            if (cinfo.quantize_colors)
            {
                cinfo.cquantize.finish_pass(cinfo);
            }
            master.pass_number++;
        }
Ejemplo n.º 34
0
		// Read next input byte; we do not support suspension in this module.
		static int get_byte_arith(jpeg_decompress cinfo)
		{
			jpeg_source_mgr src=cinfo.src;

			if(src.bytes_in_buffer==0)
			{
				if(!src.fill_input_buffer(cinfo)) ERREXIT(cinfo, J_MESSAGE_CODE.JERR_CANT_SUSPEND);
			}
			src.bytes_in_buffer--;
			return src.input_bytes[src.next_input_byte++];
		}
Ejemplo n.º 35
0
		// Undifferencers for the all rows but the first in a scan or restart interval.
		// The first sample in the row is undifferenced using the vertical
		// predictor (2). The rest of the samples are undifferenced using the
		// predictor specified in the scan header.
		static void jpeg_undifference1(jpeg_decompress cinfo, int comp_index, int[] diff_buf, int[] prev_row, int[] undiff_buf, uint width)
		{
			int Ra=(diff_buf[0]+prev_row[0])&0xFFFF;
			undiff_buf[0]=Ra;

			for(uint xindex=1; xindex<width; xindex++)
			{
				Ra=(diff_buf[xindex]+Ra)&0xFFFF;
				undiff_buf[xindex]=Ra;
			}
		}
Ejemplo n.º 36
0
		// Initialize for a Huffman-compressed scan.
		static void start_pass_huff_decoder(jpeg_decompress cinfo)
		{
			jpeg_lossy_d_codec lossyd=(jpeg_lossy_d_codec)cinfo.coef;
			shuff_entropy_decoder entropy=(shuff_entropy_decoder)lossyd.entropy_private;

			// Check that the scan parameters Ss, Se, Ah/Al are OK for sequential JPEG.
			// This ought to be an error condition, but we make it a warning because
			// there are some baseline files out there with all zeroes in these bytes.
			if(cinfo.Ss!=0||cinfo.Se!=DCTSIZE2-1||cinfo.Ah!=0||cinfo.Al!=0) WARNMS(cinfo, J_MESSAGE_CODE.JWRN_NOT_SEQUENTIAL);

			for(int ci=0; ci<cinfo.comps_in_scan; ci++)
			{
				jpeg_component_info compptr=cinfo.cur_comp_info[ci];
				int dctbl=compptr.dc_tbl_no;
				int actbl=compptr.ac_tbl_no;

				// Compute derived values for Huffman tables
				// We may do this more than once for a table, but it's not expensive
				jpeg_make_d_derived_tbl(cinfo, true, dctbl, ref entropy.dc_derived_tbls[dctbl]);
				jpeg_make_d_derived_tbl(cinfo, false, actbl, ref entropy.ac_derived_tbls[actbl]);

				// Initialize DC predictions to 0
				entropy.saved.last_dc_val[ci]=0;
			}

			// Precalculate decoding info for each block in an MCU of this scan
			for(int blkn=0; blkn<cinfo.blocks_in_MCU; blkn++)
			{
				int ci=cinfo.MCU_membership[blkn];
				jpeg_component_info compptr=cinfo.cur_comp_info[ci];

				// Precalculate which table to use for each block
				entropy.dc_cur_tbls[blkn]=entropy.dc_derived_tbls[compptr.dc_tbl_no];
				entropy.ac_cur_tbls[blkn]=entropy.ac_derived_tbls[compptr.ac_tbl_no];

				// Decide whether we really care about the coefficient values
				if(compptr.component_needed)
				{
					entropy.dc_needed[blkn]=true;
					// we don't need the ACs if producing a 1/8th-size image
					entropy.ac_needed[blkn]=(compptr.DCT_scaled_size>1);
				}
				else entropy.dc_needed[blkn]=entropy.ac_needed[blkn]=false;
			}

			// Initialize bitread state variables
			entropy.bitstate.bits_left=0;
			entropy.bitstate.get_buffer=0; // unnecessary, but keeps Purify quiet
			entropy.insufficient_data=false;

			// Initialize restart counter
			entropy.restarts_to_go=cinfo.restart_interval;
		}
Ejemplo n.º 37
0
        // Initialize coefficient buffer controller.
        static void jinit_d_coef_controller(jpeg_decompress cinfo, bool need_full_buffer)
        {
            jpeg_lossy_d_codec lossyd = (jpeg_lossy_d_codec)cinfo.coef;
            d_coef_controller  coef   = null;

            try
            {
                coef = new d_coef_controller();
            }
            catch
            {
                ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_OUT_OF_MEMORY, 4);
            }
            lossyd.coef_private           = coef;
            lossyd.coef_start_input_pass  = start_input_pass_d_coef;
            lossyd.coef_start_output_pass = start_output_pass_d_coef;
#if BLOCK_SMOOTHING_SUPPORTED
            coef.coef_bits_latch = null;
#endif

            // Create the coefficient buffer.
            if (need_full_buffer)
            {
#if D_MULTISCAN_FILES_SUPPORTED
                // Allocate a full-image array for each component,
                // padded to a multiple of samp_factor DCT blocks in each direction.
                // Note we ask for a pre-zeroed array.
                for (int ci = 0; ci < cinfo.num_components; ci++)
                {
                    jpeg_component_info compptr = cinfo.comp_info[ci];
                    int access_rows             = compptr.v_samp_factor;
                    coef.whole_image[ci] = alloc_barray(cinfo, (uint)jround_up(compptr.width_in_blocks, compptr.h_samp_factor), (uint)jround_up(compptr.height_in_blocks, compptr.v_samp_factor));
                }
                lossyd.consume_data    = consume_data;
                lossyd.decompress_data = decompress_data;
                lossyd.coef_arrays     = coef.whole_image;           // link to arrays
#else
                ERREXIT(cinfo, J_MESSAGE_CODE.JERR_NOT_COMPILED);
#endif
            }
            else
            {
                // We only need a single-MCU buffer.
                for (int i = 0; i < D_MAX_BLOCKS_IN_MCU; i++)
                {
                    coef.MCU_buffer[i] = new short[DCTSIZE2];
                }

                lossyd.consume_data    = dummy_consume_data_d_coef;
                lossyd.decompress_data = decompress_onepass;
                lossyd.coef_arrays     = null;           // flag for no arrays
            }
        }
Ejemplo n.º 38
0
        // Undifferencers for the all rows but the first in a scan or restart interval.
        // The first sample in the row is undifferenced using the vertical
        // predictor (2). The rest of the samples are undifferenced using the
        // predictor specified in the scan header.
        static void jpeg_undifference1(jpeg_decompress cinfo, int comp_index, int[] diff_buf, int[] prev_row, int[] undiff_buf, uint width)
        {
            int Ra = (diff_buf[0] + prev_row[0]) & 0xFFFF;

            undiff_buf[0] = Ra;

            for (uint xindex = 1; xindex < width; xindex++)
            {
                Ra = (diff_buf[xindex] + Ra) & 0xFFFF;
                undiff_buf[xindex] = Ra;
            }
        }
Ejemplo n.º 39
0
        static void simple_downscale(jpeg_decompress cinfo, int[] diff_buf, byte[] output_buf, uint width)
        {
            jpeg_lossless_d_codec losslsd = (jpeg_lossless_d_codec)cinfo.coef;
            scaler scaler = (scaler)losslsd.scaler_private;

            int scale_factor = scaler.scale_factor;

            for (uint xindex = 0; xindex < width; xindex++)
            {
                output_buf[xindex] = (byte)(diff_buf[xindex] >> scale_factor);
            }
        }
Ejemplo n.º 40
0
		// Initialize the decompression codec.
		// This is called only once, during master selection.
		static void jinit_d_codec(jpeg_decompress cinfo)
		{
			if(cinfo.process==J_CODEC_PROCESS.JPROC_LOSSLESS)
			{
#if D_LOSSLESS_SUPPORTED
				jinit_lossless_d_codec(cinfo);
#else
				ERREXIT(cinfo, J_MESSAGE_CODE.JERR_NOT_COMPILED);
#endif
			}
			else jinit_lossy_d_codec(cinfo);
		}
Ejemplo n.º 41
0
        // Initialize for a processing pass.
        static void start_pass_dpost(jpeg_decompress cinfo, J_BUF_MODE pass_mode)
        {
            my_post_controller post = (my_post_controller)cinfo.post;

            switch (pass_mode)
            {
            case J_BUF_MODE.JBUF_PASS_THRU:
                if (cinfo.quantize_colors)
                {
                    // Single-pass processing with color quantization.
                    post.post_process_data = post_process_1pass;

                    // We could be doing buffered-image output before starting a 2-pass
                    // color quantization; in that case, jinit_d_post_controller did not
                    // allocate a strip buffer. Use the virtual-array buffer as workspace.
                    if (post.buffer == null)
                    {
                        post.buffer        = post.whole_image;
                        post.buffer_offset = 0;
                    }
                }
                else
                {
                    // For single-pass processing without color quantization,
                    // I have no work to do; just call the upsampler directly.
                    post.post_process_data = cinfo.upsample.upsample;
                }
                break;

#if QUANT_2PASS_SUPPORTED
            case J_BUF_MODE.JBUF_SAVE_AND_PASS:
                // First pass of 2-pass quantization
                if (post.whole_image == null)
                {
                    ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_BUFFER_MODE);
                }
                post.post_process_data = post_process_prepass;
                break;

            case J_BUF_MODE.JBUF_CRANK_DEST:
                // Second pass of 2-pass quantization
                if (post.whole_image == null)
                {
                    ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_BUFFER_MODE);
                }
                post.post_process_data = post_process_2pass;
                break;
#endif // QUANT_2PASS_SUPPORTED
            default: ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_BUFFER_MODE); break;
            }
            post.starting_row = post.next_row = 0;
        }
Ejemplo n.º 42
0
		// Decompression initialization.
		// jpeg_read_header must be completed before calling this.
		//
		// If a multipass operating mode was selected, this will do all but the
		// last pass, and thus may take a great deal of time.
		//
		// Returns false if suspended. The return value need be inspected only if
		// a suspending data source is used.
		public static bool jpeg_start_decompress(jpeg_decompress cinfo)
		{
			if(cinfo.global_state==STATE.DREADY)
			{
				// First call: initialize master control, select active modules
				jinit_master_decompress(cinfo);
				if(cinfo.buffered_image)
				{
					// No more work here; expecting jpeg_start_output next
					cinfo.global_state=STATE.DBUFIMAGE;
					return true;
				}
				cinfo.global_state=STATE.DPRELOAD;
			}

			if(cinfo.global_state==STATE.DPRELOAD)
			{
				// If file has multiple scans, absorb them all into the coef buffer
				if(cinfo.inputctl.has_multiple_scans)
				{
#if D_MULTISCAN_FILES_SUPPORTED
					for(; ; )
					{
						// Call progress monitor hook if present
						if(cinfo.progress!=null) cinfo.progress.progress_monitor(cinfo);
						// Absorb some more input
						CONSUME_INPUT retcode=cinfo.inputctl.consume_input(cinfo);
						if(retcode==CONSUME_INPUT.JPEG_SUSPENDED) return false;
						if(retcode==CONSUME_INPUT.JPEG_REACHED_EOI) break;

						// Advance progress counter if appropriate
						if(cinfo.progress!=null&&(retcode==CONSUME_INPUT.JPEG_ROW_COMPLETED||retcode==CONSUME_INPUT.JPEG_REACHED_SOS))
						{
							if(++cinfo.progress.pass_counter>=cinfo.progress.pass_limit)
							{
								// jdmaster underestimated number of scans; ratchet up one scan
								cinfo.progress.pass_limit+=(int)cinfo.total_iMCU_rows;
							}
						}
					}
#else
					ERREXIT(cinfo, J_MESSAGE_CODE.JERR_NOT_COMPILED);
#endif // D_MULTISCAN_FILES_SUPPORTED
				}
				cinfo.output_scan_number=cinfo.input_scan_number;
			}
			else if(cinfo.global_state!=STATE.DPRESCAN) ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_BAD_STATE, cinfo.global_state);

			// Perform any dummy output passes, and set up for the final pass
			return output_pass_setup(cinfo);
		}
Ejemplo n.º 43
0
        // Convert grayscale to RGB: just duplicate the graylevel three times.
        // This is provided to support applications that don't want to cope
        // with grayscale as a separate case.
        static void gray_rgb_convert(jpeg_decompress cinfo, byte[][][] input_buf, uint input_row, byte[][] output_buf, uint output_row, int num_rows)
        {
            uint num_cols = cinfo.output_width;

            while (--num_rows >= 0)
            {
                byte[] inptr  = input_buf[0][input_row++];
                byte[] outptr = output_buf[output_row++];
                for (uint col = 0, outptr_ind = 0; col < num_cols; col++, outptr_ind += RGB_PIXELSIZE)
                {
                    outptr[outptr_ind + RGB_RED] = outptr[outptr_ind + RGB_GREEN] = outptr[outptr_ind + RGB_BLUE] = inptr[col];
                }
            }
        }
Ejemplo n.º 44
0
        // Read next input byte; we do not support suspension in this module.
        static int get_byte_arith(jpeg_decompress cinfo)
        {
            jpeg_source_mgr src = cinfo.src;

            if (src.bytes_in_buffer == 0)
            {
                if (!src.fill_input_buffer(cinfo))
                {
                    ERREXIT(cinfo, J_MESSAGE_CODE.JERR_CANT_SUSPEND);
                }
            }
            src.bytes_in_buffer--;
            return(src.input_bytes[src.next_input_byte++]);
        }
Ejemplo n.º 45
0
		static void jpeg_undifference5(jpeg_decompress cinfo, int comp_index, int[] diff_buf, int[] prev_row, int[] undiff_buf, uint width)
		{
			int Rb=prev_row[0];
			int Ra=(diff_buf[0]+Rb)&0xFFFF;
			undiff_buf[0]=Ra;

			for(uint xindex=1; xindex<width; xindex++)
			{
				int Rc=Rb;
				Rb=prev_row[xindex];
				Ra=(diff_buf[xindex]+Ra+((Rb-Rc)>>1))&0xFFFF;
				undiff_buf[xindex]=Ra;
			}
		}
Ejemplo n.º 46
0
		// Initialize for an output processing pass.
		static void start_output_pass_d_coef(jpeg_decompress cinfo)
		{
#if BLOCK_SMOOTHING_SUPPORTED
			jpeg_lossy_d_codec lossyd=(jpeg_lossy_d_codec)cinfo.coef;
			d_coef_controller coef=(d_coef_controller)lossyd.coef_private;

			// If multipass, check to see whether to use block smoothing on this pass
			if(lossyd.coef_arrays!=null)
			{
				if(cinfo.do_block_smoothing&&smoothing_ok(cinfo)) lossyd.decompress_data=decompress_smooth_data;
				else lossyd.decompress_data=decompress_data;
			}
#endif
			cinfo.output_iMCU_row=0;
		}
Ejemplo n.º 47
0
		static void jinit_d_scaler(jpeg_decompress cinfo)
		{
			jpeg_lossless_d_codec losslsd=(jpeg_lossless_d_codec)cinfo.coef;
			scaler scaler=null;

			try
			{
				scaler=new scaler();
			}
			catch
			{
				ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_OUT_OF_MEMORY, 4);
			}

			losslsd.scaler_private=scaler;
			losslsd.scaler_start_pass=scaler_start_pass;
		}
Ejemplo n.º 48
0
		// Set up for an output pass, and perform any dummy pass(es) needed.
		// Common subroutine for jpeg_start_decompress and jpeg_start_output.
		// Entry: global_state = DPRESCAN only if previously suspended.
		// Exit:	If done, returns true and sets global_state for proper output mode.
		//			If suspended, returns false and sets global_state = DPRESCAN.
		static bool output_pass_setup(jpeg_decompress cinfo)
		{
			if(cinfo.global_state!=STATE.DPRESCAN)
			{
				// First call: do pass setup
				cinfo.master.prepare_for_output_pass(cinfo);
				cinfo.output_scanline=0;
				cinfo.global_state=STATE.DPRESCAN;
			}

			// Loop over any required dummy passes
			while(cinfo.master.is_dummy_pass)
			{
#if QUANT_2PASS_SUPPORTED
				// Crank through the dummy pass
				while(cinfo.output_scanline<cinfo.output_height)
				{
					// Call progress monitor hook if present
					if(cinfo.progress!=null)
					{
						cinfo.progress.pass_counter=(int)cinfo.output_scanline;
						cinfo.progress.pass_limit=(int)cinfo.output_height;
						cinfo.progress.progress_monitor(cinfo);
					}

					// Process some data
					uint last_scanline=cinfo.output_scanline;
					cinfo.main.process_data(cinfo, null, ref cinfo.output_scanline, 0);
					if(cinfo.output_scanline==last_scanline) return false; // No progress made, must suspend
				}

				// Finish up dummy pass, and set up for another one
				cinfo.master.finish_output_pass(cinfo);
				cinfo.master.prepare_for_output_pass(cinfo);
				cinfo.output_scanline=0;
#else
				ERREXIT(cinfo, J_MESSAGE_CODE.JERR_NOT_COMPILED);
#endif // QUANT_2PASS_SUPPORTED
			}

			// Ready for application to drive output pass through
			// jpeg_read_scanlines or jpeg_read_raw_data.
			cinfo.global_state=cinfo.raw_data_out?STATE.DRAW_OK:STATE.DSCANNING;
			return true;
		}
Ejemplo n.º 49
0
		public const int SAVED_COEFS=6;		// we save coef_bits[0..5]

		// Reset within-iMCU-row counters for a new row (input side)
		static void start_iMCU_row_d_coef(jpeg_decompress cinfo)
		{
			jpeg_lossy_d_codec lossyd=(jpeg_lossy_d_codec)cinfo.coef;
			d_coef_controller coef=(d_coef_controller)lossyd.coef_private;

			// In an interleaved scan, an MCU row is the same as an iMCU row.
			// In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows.
			// But at the bottom of the image, process only what's left.
			if(cinfo.comps_in_scan>1) coef.MCU_rows_per_iMCU_row=1;
			else
			{
				if(cinfo.input_iMCU_row<(cinfo.total_iMCU_rows-1)) coef.MCU_rows_per_iMCU_row=cinfo.cur_comp_info[0].v_samp_factor;
				else coef.MCU_rows_per_iMCU_row=cinfo.cur_comp_info[0].last_row_height;
			}

			coef.MCU_ctr=0;
			coef.MCU_vert_offset=0;
		}
Ejemplo n.º 50
0
		// Initialize for a processing pass.
		static void start_pass_dpost(jpeg_decompress cinfo, J_BUF_MODE pass_mode)
		{
			my_post_controller post=(my_post_controller)cinfo.post;

			switch(pass_mode)
			{
				case J_BUF_MODE.JBUF_PASS_THRU:
					if(cinfo.quantize_colors)
					{
						// Single-pass processing with color quantization.
						post.post_process_data=post_process_1pass;

						// We could be doing buffered-image output before starting a 2-pass
						// color quantization; in that case, jinit_d_post_controller did not
						// allocate a strip buffer. Use the virtual-array buffer as workspace.
						if(post.buffer==null)
						{
							post.buffer=post.whole_image;
							post.buffer_offset=0;
						}
					}
					else
					{
						// For single-pass processing without color quantization,
						// I have no work to do; just call the upsampler directly.
						post.post_process_data=cinfo.upsample.upsample;
					}
					break;
#if QUANT_2PASS_SUPPORTED
				case J_BUF_MODE.JBUF_SAVE_AND_PASS:
					// First pass of 2-pass quantization
					if(post.whole_image==null) ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_BUFFER_MODE);
					post.post_process_data=post_process_prepass;
					break;
				case J_BUF_MODE.JBUF_CRANK_DEST:
					// Second pass of 2-pass quantization
					if(post.whole_image==null) ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_BUFFER_MODE);
					post.post_process_data=post_process_2pass;
					break;
#endif // QUANT_2PASS_SUPPORTED
				default: ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_BUFFER_MODE); break;
			}
			post.starting_row=post.next_row=0;
		}
Ejemplo n.º 51
0
		// Initialize the lossless decompression codec.
		// This is called only once, during master selection.
		static void jinit_lossless_d_codec(jpeg_decompress cinfo)
		{
			jpeg_lossless_d_codec losslsd=null;

			// Create subobject
			try
			{
				losslsd=new jpeg_lossless_d_codec();
			}
			catch
			{
				ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_OUT_OF_MEMORY, 4);
			}

			cinfo.coef=losslsd;

			// Initialize sub-modules
			// Entropy decoding: either Huffman or arithmetic coding.
			if(cinfo.arith_code)
			{
				ERREXIT(cinfo, J_MESSAGE_CODE.JERR_ARITH_NOTIMPL);
			}
			else
			{
				jinit_lhuff_decoder(cinfo);
			}

			// Undifferencer
			jinit_undifferencer(cinfo);

			// Scaler
			jinit_d_scaler(cinfo);

			bool use_c_buffer=cinfo.inputctl.has_multiple_scans||cinfo.buffered_image;
			jinit_d_diff_controller(cinfo, use_c_buffer);

			// Initialize method pointers.
			//
			// Note: consume_data, start_output_pass and decompress_data are
			// assigned in jddiffct.cs.
			losslsd.calc_output_dimensions=calc_output_dimensions_ls;
			losslsd.start_input_pass=start_input_pass_ls;
		}
Ejemplo n.º 52
0
		static void scaler_start_pass(jpeg_decompress cinfo)
		{
			jpeg_lossless_d_codec losslsd=(jpeg_lossless_d_codec)cinfo.coef;
			scaler scaler=(scaler)losslsd.scaler_private;

			// Downscale by the difference in the input vs. output precision. If the
			// output precision >= input precision, then do not downscale.
			int downscale=BITS_IN_JSAMPLE<cinfo.data_precision?cinfo.data_precision-BITS_IN_JSAMPLE:0;

			scaler.scale_factor=cinfo.Al-downscale;

			// Set scaler functions based on scale_factor (positive = left shift)
			if(scaler.scale_factor>0) losslsd.scaler_scale=simple_upscale;
			else if(scaler.scale_factor<0)
			{
				scaler.scale_factor=-scaler.scale_factor;
				losslsd.scaler_scale=simple_downscale;
			}
			else losslsd.scaler_scale=noscale;
		}
Ejemplo n.º 53
0
		// Save away a copy of the Q-table referenced by each component present
		// in the current scan, unless already saved during a prior scan.
		//
		// In a multiple-scan JPEG file, the encoder could assign different components
		// the same Q-table slot number, but change table definitions between scans
		// so that each component uses a different Q-table. (The IJG encoder is not
		// currently capable of doing this, but other encoders might.) Since we want
		// to be able to dequantize all the components at the end of the file, this
		// means that we have to save away the table actually used for each component.
		// We do this by copying the table at the start of the first scan containing
		// the component.
		// The JPEG spec prohibits the encoder from changing the contents of a Q-table
		// slot between scans of a component using that slot. If the encoder does so
		// anyway, this decoder will simply use the Q-table values that were current
		// at the start of the first scan for the component.
		//
		// The decompressor output side looks only at the saved quant tables,
		// not at the current Q-table slots.
		static void latch_quant_tables_lossy(jpeg_decompress cinfo)
		{
			for(int ci=0; ci<cinfo.comps_in_scan; ci++)
			{
				jpeg_component_info compptr=cinfo.cur_comp_info[ci];
				// No work if we already saved Q-table for this component
				if(compptr.quant_table!=null) continue;

				// Make sure specified quantization table is present
				int qtblno=compptr.quant_tbl_no;
				if(qtblno<0||qtblno>=NUM_QUANT_TBLS||cinfo.quant_tbl_ptrs[qtblno]==null) ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_NO_QUANT_TABLE, qtblno);

				// OK, save away the quantization table
				JQUANT_TBL qtbl=new JQUANT_TBL();

				cinfo.quant_tbl_ptrs[qtblno].quantval.CopyTo(qtbl.quantval, 0);
				qtbl.sent_table=cinfo.quant_tbl_ptrs[qtblno].sent_table;

				compptr.quant_table=qtbl;
			}
		}
Ejemplo n.º 54
0
		// Compute output image dimensions and related values.
		// NOTE: this is exported for possible use by application.
		// Hence it mustn't do anything that can't be done twice.
		// Also note that it may be called before the master module is initialized!

		// Do computations that are needed before master selection phase
		public static void jpeg_calc_output_dimensions(jpeg_decompress cinfo)
		{
			// Prevent application from calling me at wrong times
			if(cinfo.global_state!=STATE.DREADY) ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_BAD_STATE, cinfo.global_state);

			cinfo.coef.calc_output_dimensions(cinfo);

			// Report number of components in selected colorspace.
			// Probably this should be in the color conversion module...
			switch(cinfo.out_color_space)
			{
				case J_COLOR_SPACE.JCS_GRAYSCALE: cinfo.out_color_components=1; break;
				case J_COLOR_SPACE.JCS_RGB:
				case J_COLOR_SPACE.JCS_YCbCr: cinfo.out_color_components=3; break;
				case J_COLOR_SPACE.JCS_CMYK:
				case J_COLOR_SPACE.JCS_YCCK: cinfo.out_color_components=4; break;
				default: cinfo.out_color_components=cinfo.num_components; break; // else must be same colorspace as in file
			}
			cinfo.output_components=(cinfo.quantize_colors?1:cinfo.out_color_components);

			// See if upsampler will want to emit more than one row at a time
			if(use_merged_upsample(cinfo)) cinfo.rec_outbuf_height=cinfo.max_v_samp_factor;
			else cinfo.rec_outbuf_height=1;
		}
Ejemplo n.º 55
0
		// Initialize for an input processing pass.
		static void start_input_pass_d_coef(jpeg_decompress cinfo)
		{
			cinfo.input_iMCU_row=0;
			start_iMCU_row_d_coef(cinfo);
		}
Ejemplo n.º 56
0
		// Initialize coefficient buffer controller.
		static void jinit_d_coef_controller(jpeg_decompress cinfo, bool need_full_buffer)
		{
			jpeg_lossy_d_codec lossyd=(jpeg_lossy_d_codec)cinfo.coef;
			d_coef_controller coef=null;

			try
			{
				coef=new d_coef_controller();
			}
			catch
			{
				ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_OUT_OF_MEMORY, 4);
			}
			lossyd.coef_private=coef;
			lossyd.coef_start_input_pass=start_input_pass_d_coef;
			lossyd.coef_start_output_pass=start_output_pass_d_coef;
#if BLOCK_SMOOTHING_SUPPORTED
			coef.coef_bits_latch=null;
#endif

			// Create the coefficient buffer.
			if(need_full_buffer)
			{
#if D_MULTISCAN_FILES_SUPPORTED
				// Allocate a full-image array for each component,
				// padded to a multiple of samp_factor DCT blocks in each direction.
				// Note we ask for a pre-zeroed array.
				for(int ci=0; ci<cinfo.num_components; ci++)
				{
					jpeg_component_info compptr=cinfo.comp_info[ci];
					int access_rows=compptr.v_samp_factor;
					coef.whole_image[ci]=alloc_barray(cinfo, (uint)jround_up(compptr.width_in_blocks, compptr.h_samp_factor), (uint)jround_up(compptr.height_in_blocks, compptr.v_samp_factor));
				}
				lossyd.consume_data=consume_data;
				lossyd.decompress_data=decompress_data;
				lossyd.coef_arrays=coef.whole_image; // link to arrays
#else
				ERREXIT(cinfo, J_MESSAGE_CODE.JERR_NOT_COMPILED);
#endif
			}
			else
			{
				// We only need a single-MCU buffer.
				for(int i=0; i<D_MAX_BLOCKS_IN_MCU; i++) coef.MCU_buffer[i]=new short[DCTSIZE2];

				lossyd.consume_data=dummy_consume_data_d_coef;
				lossyd.decompress_data=decompress_onepass;
				lossyd.coef_arrays=null; // flag for no arrays
			}
		}
Ejemplo n.º 57
0
		// Variant of decompress_data for use when doing block smoothing.
		static CONSUME_INPUT decompress_smooth_data(jpeg_decompress cinfo, byte[][][] output_buf)
		{
			jpeg_lossy_d_codec lossyd=(jpeg_lossy_d_codec)cinfo.coef;
			d_coef_controller coef=(d_coef_controller)lossyd.coef_private;

			// Force some input to be done if we are getting ahead of the input.
			while(cinfo.input_scan_number<=cinfo.output_scan_number&&!cinfo.inputctl.eoi_reached)
			{
				if(cinfo.input_scan_number==cinfo.output_scan_number)
				{
					// If input is working on current scan, we ordinarily want it to
					// have completed the current row. But if input scan is DC,
					// we want it to keep one row ahead so that next block row's DC
					// values are up to date.
					uint delta=(cinfo.Ss==0)?1u:0u;
					if(cinfo.input_iMCU_row>cinfo.output_iMCU_row+delta) break;
				}
				if(cinfo.inputctl.consume_input(cinfo)==CONSUME_INPUT.JPEG_SUSPENDED) return CONSUME_INPUT.JPEG_SUSPENDED;
			}

			uint last_iMCU_row=cinfo.total_iMCU_rows-1;
			short[] workspace=new short[DCTSIZE2];

			// OK, output from the arrays.
			for(int ci=0; ci<cinfo.num_components; ci++)
			{
				jpeg_component_info compptr=cinfo.comp_info[ci];

				// Don't bother to IDCT an uninteresting component.
				if(!compptr.component_needed) continue;

				// Count non-dummy DCT block rows in this iMCU row.
				int block_rows, access_rows;
				bool last_row;
				if(cinfo.output_iMCU_row<last_iMCU_row)
				{
					block_rows=compptr.v_samp_factor;
					access_rows=block_rows*2; // this and next iMCU row
					last_row=false;
				}
				else
				{
					// NB: can't use last_row_height here; it is input-side-dependent!
					block_rows=(int)(compptr.height_in_blocks%compptr.v_samp_factor);
					if(block_rows==0) block_rows=compptr.v_samp_factor;
					access_rows=block_rows; // this iMCU row only
					last_row=true;
				}

				// Align the buffer for this component.
				bool first_row;
				short[][][] buffer;
				int buffer_ind;
				if(cinfo.output_iMCU_row>0)
				{
					access_rows+=compptr.v_samp_factor; // prior iMCU row too
					buffer=coef.whole_image[ci];
					buffer_ind=(int)cinfo.output_iMCU_row*compptr.v_samp_factor; // point to current iMCU row
					first_row=false;
				}
				else
				{
					buffer=coef.whole_image[ci];
					buffer_ind=0;
					first_row=true;
				}

				// Fetch component-dependent info
				int[] coef_bits=coef.coef_bits_latch[ci];
				JQUANT_TBL quanttbl=compptr.quant_table;
				int Q00=quanttbl.quantval[0];
				int Q01=quanttbl.quantval[Q01_POS];
				int Q10=quanttbl.quantval[Q10_POS];
				int Q20=quanttbl.quantval[Q20_POS];
				int Q11=quanttbl.quantval[Q11_POS];
				int Q02=quanttbl.quantval[Q02_POS];
				inverse_DCT_method_ptr inverse_DCT=lossyd.inverse_DCT[ci];
				uint output_buf_ind=0;

				// Loop over all DCT blocks to be processed.
				for(int block_row=0; block_row<block_rows; block_row++)
				{
					short[][] buffer_ptr=buffer[buffer_ind+block_row];
					short[][] prev_block_row;
					short[][] next_block_row;

					if(first_row&&block_row==0) prev_block_row=buffer_ptr;
					else prev_block_row=buffer[buffer_ind+block_row-1];
					if(last_row&&block_row==block_rows-1) next_block_row=buffer_ptr;
					else next_block_row=buffer[buffer_ind+block_row+1];

					// We fetch the surrounding DC values using a sliding-register approach.
					// Initialize all nine here so as to do the right thing on narrow pics.
					int DC1, DC2, DC3, DC4, DC5, DC6, DC7, DC8, DC9;
					DC1=DC2=DC3=(int)prev_block_row[0][0];
					DC4=DC5=DC6=(int)buffer_ptr[0][0];
					DC7=DC8=DC9=(int)next_block_row[0][0];
					int ind=1;

					uint output_col=0;

					uint last_block_column=compptr.width_in_blocks-1;
					for(uint block_num=0; block_num<=last_block_column; block_num++)
					{
						// Fetch current DCT block into workspace so we can modify it.
						buffer_ptr.CopyTo(workspace, 0);

						// Update DC values
						if(block_num<last_block_column)
						{
							DC3=(int)prev_block_row[ind][0];
							DC6=(int)buffer_ptr[ind][0];
							DC9=(int)next_block_row[ind][0];
						}
						// Compute coefficient estimates per K.8.
						// An estimate is applied only if coefficient is still zero,
						// and is not known to be fully accurate.

						// AC01
						int Al=coef_bits[1];
						if(Al!=0&&workspace[1]==0)
						{
							int num=36*Q00*(DC4-DC6);
							int pred;
							if(num>=0)
							{
								pred=(int)(((Q01<<7)+num)/(Q01<<8));
								if(Al>0&&pred>=(1<<Al)) pred=(1<<Al)-1;
							}
							else
							{
								pred=(int)(((Q01<<7)-num)/(Q01<<8));
								if(Al>0&&pred>=(1<<Al)) pred=(1<<Al)-1;
								pred=-pred;
							}
							workspace[1]=(short)pred;
						}

						// AC10
						Al=coef_bits[2];
						if(Al!=0&&workspace[8]==0)
						{
							int num=36*Q00*(DC2-DC8);
							int pred;
							if(num>=0)
							{
								pred=(int)(((Q10<<7)+num)/(Q10<<8));
								if(Al>0&&pred>=(1<<Al)) pred=(1<<Al)-1;
							}
							else
							{
								pred=(int)(((Q10<<7)-num)/(Q10<<8));
								if(Al>0&&pred>=(1<<Al)) pred=(1<<Al)-1;
								pred=-pred;
							}
							workspace[8]=(short)pred;
						}

						// AC20
						Al=coef_bits[3];
						if(Al!=0&&workspace[16]==0)
						{
							int num=9*Q00*(DC2+DC8-2*DC5);
							int pred;
							if(num>=0)
							{
								pred=(int)(((Q20<<7)+num)/(Q20<<8));
								if(Al>0&&pred>=(1<<Al)) pred=(1<<Al)-1;
							}
							else
							{
								pred=(int)(((Q20<<7)-num)/(Q20<<8));
								if(Al>0&&pred>=(1<<Al)) pred=(1<<Al)-1;
								pred=-pred;
							}
							workspace[16]=(short)pred;
						}

						// AC11
						Al=coef_bits[4];
						if(Al!=0&&workspace[9]==0)
						{
							int num=5*Q00*(DC1-DC3-DC7+DC9);
							int pred;
							if(num>=0)
							{
								pred=(int)(((Q11<<7)+num)/(Q11<<8));
								if(Al>0&&pred>=(1<<Al)) pred=(1<<Al)-1;
							}
							else
							{
								pred=(int)(((Q11<<7)-num)/(Q11<<8));
								if(Al>0&&pred>=(1<<Al)) pred=(1<<Al)-1;
								pred=-pred;
							}
							workspace[9]=(short)pred;
						}

						// AC02
						Al=coef_bits[5];
						if(Al!=0&&workspace[2]==0)
						{
							int num=9*Q00*(DC4+DC6-2*DC5);
							int pred;
							if(num>=0)
							{
								pred=(int)(((Q02<<7)+num)/(Q02<<8));
								if(Al>0&&pred>=(1<<Al)) pred=(1<<Al)-1;
							}
							else
							{
								pred=(int)(((Q02<<7)-num)/(Q02<<8));
								if(Al>0&&pred>=(1<<Al)) pred=(1<<Al)-1;
								pred=-pred;
							}
							workspace[2]=(short)pred;
						}

						// OK, do the IDCT
						inverse_DCT(cinfo, compptr, workspace, output_buf[ci], output_buf_ind, output_col);

						// Advance for next column
						DC1=DC2; DC2=DC3;
						DC4=DC5; DC5=DC6;
						DC7=DC8; DC8=DC9;
						ind++;
						output_col+=compptr.DCT_scaled_size;
					}
					output_buf_ind+=compptr.DCT_scaled_size;
				}
			}

			if(++(cinfo.output_iMCU_row)<cinfo.total_iMCU_rows) return CONSUME_INPUT.JPEG_ROW_COMPLETED;
			return CONSUME_INPUT.JPEG_SCAN_COMPLETED;
		}
Ejemplo n.º 58
0
		// Determine whether block smoothing is applicable and safe.
		// We also latch the current states of the coef_bits[] entries for the
		// AC coefficients; otherwise, if the input side of the decompressor
		// advances into a new scan, we might think the coefficients are known
		// more accurately than they really are.
		static bool smoothing_ok(jpeg_decompress cinfo)
		{
			jpeg_lossy_d_codec lossyd=(jpeg_lossy_d_codec)cinfo.coef;
			d_coef_controller coef=(d_coef_controller)lossyd.coef_private;
			
			if(cinfo.process!=J_CODEC_PROCESS.JPROC_PROGRESSIVE||cinfo.coef_bits==null) return false;

			// Allocate latch area if not already done
			if(coef.coef_bits_latch==null)
			{
				try
				{
					coef.coef_bits_latch=new int[cinfo.num_components][];
					for(int i=0; i<cinfo.num_components; i++) coef.coef_bits_latch[i]=new int[SAVED_COEFS];
				}
				catch
				{
					ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_OUT_OF_MEMORY, 4);
				}
			}

			bool smoothing_useful=false;
			for(int ci=0; ci<cinfo.num_components; ci++)
			{
				jpeg_component_info compptr=cinfo.comp_info[ci];

				// All components' quantization values must already be latched.
				JQUANT_TBL qtable=compptr.quant_table;
				if(qtable==null) return false;

				// Verify DC & first 5 AC quantizers are nonzero to avoid zero-divide.
				if(qtable.quantval[0]==0||qtable.quantval[Q01_POS]==0||qtable.quantval[Q10_POS]==0||qtable.quantval[Q20_POS]==0||qtable.quantval[Q11_POS]==0||qtable.quantval[Q02_POS]==0) return false;

				// DC values must be at least partly known for all components.
				int[] coef_bits=cinfo.coef_bits[ci];
				if(coef_bits[0]<0) return false;

				// Block smoothing is helpful if some AC coefficients remain inaccurate.
				for(int coefi=1; coefi<=5; coefi++)
				{
					coef.coef_bits_latch[ci][coefi]=coef_bits[coefi];
					if(coef_bits[coefi]!=0) smoothing_useful=true;
				}
			}

			return smoothing_useful;
		}
Ejemplo n.º 59
0
		// Decompress and return some data in the multi-pass case.
		// Always attempts to emit one fully interleaved MCU row ("iMCU" row).
		// Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED.
		//
		// NB: output_buf contains a plane for each component in image.
		static CONSUME_INPUT decompress_data(jpeg_decompress cinfo, byte[][][] output_buf)
		{
			jpeg_lossy_d_codec lossyd=(jpeg_lossy_d_codec)cinfo.coef;
			d_coef_controller coef=(d_coef_controller)lossyd.coef_private;

			uint last_iMCU_row=cinfo.total_iMCU_rows-1;

			// Force some input to be done if we are getting ahead of the input.
			while(cinfo.input_scan_number<cinfo.output_scan_number||(cinfo.input_scan_number==cinfo.output_scan_number&&cinfo.input_iMCU_row<=cinfo.output_iMCU_row))
			{
				if(cinfo.inputctl.consume_input(cinfo)==CONSUME_INPUT.JPEG_SUSPENDED) return CONSUME_INPUT.JPEG_SUSPENDED;
			}

			// OK, output from the arrays.
			for(int ci=0; ci<cinfo.num_components; ci++)
			{
				jpeg_component_info compptr=cinfo.comp_info[ci];

				// Don't bother to IDCT an uninteresting component.
				if(!compptr.component_needed) continue;

				// Align the buffer for this component.
				short[][][] buffer=coef.whole_image[ci];
				uint buffer_ind=cinfo.output_iMCU_row*(uint)compptr.v_samp_factor;

				// Count non-dummy DCT block rows in this iMCU row.
				int block_rows;
				if(cinfo.output_iMCU_row<last_iMCU_row) block_rows=compptr.v_samp_factor;
				else
				{
					// NB: can't use last_row_height here; it is input-side-dependent!
					block_rows=(int)(compptr.height_in_blocks%compptr.v_samp_factor);
					if(block_rows==0) block_rows=compptr.v_samp_factor;
				}
				inverse_DCT_method_ptr inverse_DCT=lossyd.inverse_DCT[ci];
				byte[][] output_ptr=output_buf[ci];
				uint output_ptr_ind=0;

				// Loop over all DCT blocks to be processed.
				for(int block_row=0; block_row<block_rows; block_row++)
				{
					short[][] buffer_ptr=buffer[buffer_ind+block_row];
					uint output_col=0;
					for(uint block_num=0; block_num<compptr.width_in_blocks; block_num++)
					{
						inverse_DCT(cinfo, compptr, buffer_ptr[block_num], output_ptr, output_ptr_ind, output_col);
						output_col+=compptr.DCT_scaled_size;
					}
					output_ptr_ind+=compptr.DCT_scaled_size;
				}
			}

			if(++(cinfo.output_iMCU_row)<cinfo.total_iMCU_rows)	return CONSUME_INPUT.JPEG_ROW_COMPLETED;
			return CONSUME_INPUT.JPEG_SCAN_COMPLETED;
		}
Ejemplo n.º 60
0
		// Consume input data and store it in the full-image coefficient buffer.
		// We read as much as one fully interleaved MCU row ("iMCU" row) per call,
		// ie, v_samp_factor block rows for each component in the scan.
		// Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED.
		static CONSUME_INPUT consume_data(jpeg_decompress cinfo)
		{
			jpeg_lossy_d_codec lossyd=(jpeg_lossy_d_codec)cinfo.coef;
			d_coef_controller coef=(d_coef_controller)lossyd.coef_private;

			short[][][][] buffer=new short[MAX_COMPS_IN_SCAN][][][];
			int[] buffer_ind=new int[MAX_COMPS_IN_SCAN];

			// Align the buffers for the components used in this scan.
			for(int ci=0; ci<cinfo.comps_in_scan; ci++)
			{
				jpeg_component_info compptr=cinfo.cur_comp_info[ci];
				buffer[ci]=coef.whole_image[compptr.component_index];
				buffer_ind[ci]=(int)cinfo.input_iMCU_row*compptr.v_samp_factor;
				// Note: entropy decoder expects buffer to be zeroed,
				// but this is handled automatically by the memory manager
				// because we requested a pre-zeroed array.
			}

			// Loop to process one whole iMCU row
			for(int yoffset=coef.MCU_vert_offset; yoffset<coef.MCU_rows_per_iMCU_row; yoffset++)
			{
				for(uint MCU_col_num=coef.MCU_ctr; MCU_col_num<cinfo.MCUs_per_row; MCU_col_num++) // index of current MCU within row
				{
					// Construct list of pointers to DCT blocks belonging to this MCU
					int blkn=0; // index of current DCT block within MCU
					for(int ci=0; ci<cinfo.comps_in_scan; ci++)
					{
						jpeg_component_info compptr=cinfo.cur_comp_info[ci];
						uint start_col=MCU_col_num*(uint)compptr.MCU_width;
						for(int yindex=0; yindex<compptr.MCU_height; yindex++)
						{
							short[][] buffer_ptr=buffer[ci][buffer_ind[ci]+yindex+yoffset];
							uint buffer_ptr_ind=start_col;
							for(int xindex=0; xindex<compptr.MCU_width; xindex++) coef.MCU_buffer[blkn++]=buffer_ptr[buffer_ptr_ind++];
						}
					}

					// Try to fetch the MCU.
					if(!lossyd.entropy_decode_mcu(cinfo, coef.MCU_buffer))
					{
						// Suspension forced; update state counters and exit
						coef.MCU_vert_offset=yoffset;
						coef.MCU_ctr=MCU_col_num;
						return CONSUME_INPUT.JPEG_SUSPENDED;
					}
				}

				// Completed an MCU row, but perhaps not an iMCU row
				coef.MCU_ctr=0;
			}

			// Completed the iMCU row, advance counters for next one
			if(++(cinfo.input_iMCU_row)<cinfo.total_iMCU_rows)
			{
				start_iMCU_row_d_coef(cinfo);
				return CONSUME_INPUT.JPEG_ROW_COMPLETED;
			}

			// Completed the scan
			cinfo.inputctl.finish_input_pass(cinfo);
			return CONSUME_INPUT.JPEG_SCAN_COMPLETED;
		}