Пример #1
0
        // Initialize for an upsampling pass.
        static void start_pass_upsample(jpeg_decompress cinfo)
        {
            my_upsampler upsample = (my_upsampler)cinfo.upsample;

            // Mark the conversion buffer empty
            upsample.next_row_out = cinfo.max_v_samp_factor;
            // Initialize total-height counter for detecting bottom of image
            upsample.rows_to_go = cinfo.output_height;
        }
Пример #2
0
        // Control routine to do upsampling (and color conversion).
        //
        // In this version we upsample each component independently.
        // We upsample one row group into the conversion buffer, then apply
        // color conversion a row at a time.
        static void sep_upsample(jpeg_decompress cinfo, byte[][][] input_buf, ref uint in_row_group_ctr, uint in_row_groups_avail, byte[][] output_buf, uint output_buf_offset, ref uint out_row_ctr, uint out_rows_avail)
        {
            my_upsampler upsample = (my_upsampler)cinfo.upsample;

            // Fill the conversion buffer, if it's empty
            if (upsample.next_row_out >= cinfo.max_v_samp_factor)
            {
                for (int ci = 0; ci < cinfo.num_components; ci++)
                {
                    jpeg_component_info compptr = cinfo.comp_info[ci];

                    // Invoke per-component upsample method. Notice we pass a POINTER
                    // to color_buf[ci], so that fullsize_upsample can change it.
                    upsample.methods[ci](cinfo, compptr, input_buf[ci], (int)(in_row_group_ctr * upsample.rowgroup_height[ci]), upsample.color_buf, ci);
                }
                upsample.next_row_out = 0;
            }

            // Color-convert and emit rows

            // How many we have in the buffer:
            uint num_rows = (uint)(cinfo.max_v_samp_factor - upsample.next_row_out);

            // Not more than the distance to the end of the image. Need this test
            // in case the image height is not a multiple of max_v_samp_factor:
            if (num_rows > upsample.rows_to_go)
            {
                num_rows = upsample.rows_to_go;
            }

            // And not more than what the client can accept:
            out_rows_avail -= out_row_ctr;
            if (num_rows > out_rows_avail)
            {
                num_rows = out_rows_avail;
            }

            cinfo.cconvert.color_convert(cinfo, upsample.color_buf, (uint)upsample.next_row_out, output_buf, output_buf_offset + out_row_ctr, (int)num_rows);

            // Adjust counts
            out_row_ctr           += num_rows;
            upsample.rows_to_go   -= num_rows;
            upsample.next_row_out += (int)num_rows;

            // When the buffer is emptied, declare this input row group consumed
            if (upsample.next_row_out >= cinfo.max_v_samp_factor)
            {
                in_row_group_ctr++;
            }
        }
Пример #3
0
        // This version handles any integral sampling ratios.
        // This is not used for typical JPEG files, so it need not be fast.
        // Nor, for that matter, is it particularly accurate: the algorithm is
        // simple replication of the input pixel onto the corresponding output
        // pixels. The hi-falutin sampling literature refers to this as a
        // "box filter". A box filter tends to introduce visible artifacts,
        // so if you are actually going to use 3:1 or 4:1 sampling ratios
        // you would be well advised to improve this code.
        static void int_upsample(jpeg_decompress cinfo, jpeg_component_info compptr, byte[][] input_data, int input_data_offset, byte[][][] output_data_ptr, int output_data_offset)
        {
            my_upsampler upsample = (my_upsampler)cinfo.upsample;

            byte[][] output_data = output_data_ptr[output_data_offset];

            int h_expand = upsample.h_expand[compptr.component_index];
            int v_expand = upsample.v_expand[compptr.component_index];

            int  outrow = 0;
            uint outend = cinfo.output_width;

            while (outrow < cinfo.max_v_samp_factor)
            {
                // Generate one output row with proper horizontal expansion
                byte[] inptr      = input_data[input_data_offset];
                uint   inptr_ind  = 0;
                byte[] outptr     = output_data[outrow];
                uint   outptr_ind = 0;
                while (outptr_ind < outend)
                {
                    byte invalue = inptr[inptr_ind++];
                    for (int h = h_expand; h > 0; h--)
                    {
                        outptr[outptr_ind++] = invalue;
                    }
                }

                // Generate any additional output rows by duplicating the first one
                if (v_expand > 1)
                {
                    jcopy_sample_rows(output_data, outrow, output_data, outrow + 1, v_expand - 1, cinfo.output_width);
                }
                input_data_offset++;
                outrow += v_expand;
            }
        }
Пример #4
0
        // Module initialization routine for upsampling.
        public static void jinit_upsampler(jpeg_decompress cinfo)
        {
            my_upsampler upsample = null;
            bool         need_buffer;
            int          h_in_group, v_in_group, h_out_group, v_out_group;

            try
            {
                upsample = new my_upsampler();
            }
            catch
            {
                ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_OUT_OF_MEMORY, 4);
            }
            cinfo.upsample      = upsample;
            upsample.start_pass = start_pass_upsample;
            upsample.upsample   = sep_upsample;
#if UPSCALING_CONTEXT
            upsample.need_context_rows = false;           // until we find out differently
#endif

            if (cinfo.CCIR601_sampling)
            {
                ERREXIT(cinfo, J_MESSAGE_CODE.JERR_CCIR601_NOTIMPL);                                    // this isn't supported
            }
            // jdmainct.cs doesn't support context rows when min_DCT_scaled_size = 1,
            // so don't ask for it.
            bool do_fancy = cinfo.do_fancy_upsampling && cinfo.min_DCT_scaled_size > 1;

            // Verify we can handle the sampling factors, select per-component methods,
            // and create storage as needed.
            for (int ci = 0; ci < cinfo.num_components; ci++)
            {
                jpeg_component_info compptr = cinfo.comp_info[ci];

                // Compute size of an "input group" after IDCT scaling. This many samples
                // are to be converted to max_h_samp_factor * max_v_samp_factor pixels.
                h_in_group  = (int)(compptr.h_samp_factor * compptr.DCT_scaled_size) / cinfo.min_DCT_scaled_size;
                v_in_group  = (int)(compptr.v_samp_factor * compptr.DCT_scaled_size) / cinfo.min_DCT_scaled_size;
                h_out_group = cinfo.max_h_samp_factor;
                v_out_group = cinfo.max_v_samp_factor;
                upsample.rowgroup_height[ci] = v_in_group;               // save for use later
                need_buffer = true;
                if (!compptr.component_needed)
                {
                    // Don't bother to upsample an uninteresting component.
                    upsample.methods[ci] = noop_upsample;
                    need_buffer          = false;
                }
                else if (h_in_group == h_out_group && v_in_group == v_out_group)
                {
                    // Fullsize components can be processed without any work.
                    upsample.methods[ci]   = fullsize_upsample;
                    need_buffer            = false;
                    upsample.color_buf[ci] = new byte[cinfo.max_v_samp_factor][];
                }
                else if (h_in_group * 2 == h_out_group && v_in_group == v_out_group)
                {
                    // Special cases for 2h1v upsampling
                    if (do_fancy && compptr.downsampled_width > 2)
                    {
                        upsample.methods[ci] = h2v1_fancy_upsample;
                    }
                    else
                    {
                        upsample.methods[ci] = h2v1_upsample;
                    }
                }
                else if (h_in_group * 2 == h_out_group && v_in_group * 2 == v_out_group)
                {
                    // Special cases for 2h2v upsampling
#if UPSCALING_CONTEXT
                    if (do_fancy && compptr.downsampled_width > 2)
                    {
                        upsample.methods[ci]       = h2v2_fancy_upsample;
                        upsample.need_context_rows = true;
                        compptr.doContext          = true;
                    }
                    else
#endif
                    upsample.methods[ci] = h2v2_upsample;
                }
                else if ((h_out_group % h_in_group) == 0 && (v_out_group % v_in_group) == 0)
                {
                    // Generic integral-factors upsampling method
                    upsample.methods[ci]  = int_upsample;
                    upsample.h_expand[ci] = (byte)(h_out_group / h_in_group);
                    upsample.v_expand[ci] = (byte)(v_out_group / v_in_group);
                }
                else
                {
                    ERREXIT(cinfo, J_MESSAGE_CODE.JERR_FRACT_SAMPLE_NOTIMPL);
                }

                if (need_buffer)
                {
                    upsample.color_buf[ci] = alloc_sarray(cinfo, (uint)jround_up((int)cinfo.output_width, (int)cinfo.max_h_samp_factor), (uint)cinfo.max_v_samp_factor);
                }
            }
        }
Пример #5
0
		// Module initialization routine for upsampling.
		public static void jinit_upsampler(jpeg_decompress cinfo)
		{
			my_upsampler upsample=null;
			bool need_buffer;
			int h_in_group, v_in_group, h_out_group, v_out_group;

			try
			{
				upsample=new my_upsampler();
			}
			catch
			{
				ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_OUT_OF_MEMORY, 4);
			}
			cinfo.upsample=upsample;
			upsample.start_pass=start_pass_upsample;
			upsample.upsample=sep_upsample;
#if UPSCALING_CONTEXT
			upsample.need_context_rows=false; // until we find out differently
#endif

			if(cinfo.CCIR601_sampling) ERREXIT(cinfo, J_MESSAGE_CODE.JERR_CCIR601_NOTIMPL); // this isn't supported

			// jdmainct.cs doesn't support context rows when min_DCT_scaled_size = 1,
			// so don't ask for it.
			bool do_fancy=cinfo.do_fancy_upsampling&&cinfo.min_DCT_scaled_size>1;

			// Verify we can handle the sampling factors, select per-component methods,
			// and create storage as needed.
			for(int ci=0; ci<cinfo.num_components; ci++)
			{
				jpeg_component_info compptr=cinfo.comp_info[ci];

				// Compute size of an "input group" after IDCT scaling. This many samples
				// are to be converted to max_h_samp_factor * max_v_samp_factor pixels.
				h_in_group=(int)(compptr.h_samp_factor*compptr.DCT_scaled_size)/cinfo.min_DCT_scaled_size;
				v_in_group=(int)(compptr.v_samp_factor*compptr.DCT_scaled_size)/cinfo.min_DCT_scaled_size;
				h_out_group=cinfo.max_h_samp_factor;
				v_out_group=cinfo.max_v_samp_factor;
				upsample.rowgroup_height[ci]=v_in_group; // save for use later
				need_buffer=true;
				if(!compptr.component_needed)
				{
					// Don't bother to upsample an uninteresting component.
					upsample.methods[ci]=noop_upsample;
					need_buffer=false;
				}
				else if(h_in_group==h_out_group&&v_in_group==v_out_group)
				{
					// Fullsize components can be processed without any work.
					upsample.methods[ci]=fullsize_upsample;
					need_buffer=false;
					upsample.color_buf[ci]=new byte[cinfo.max_v_samp_factor][];
				}
				else if(h_in_group*2==h_out_group&&v_in_group==v_out_group)
				{
					// Special cases for 2h1v upsampling
					if(do_fancy&&compptr.downsampled_width>2) upsample.methods[ci]=h2v1_fancy_upsample;
					else upsample.methods[ci]=h2v1_upsample;
				}
				else if(h_in_group*2==h_out_group&&v_in_group*2==v_out_group)
				{
					// Special cases for 2h2v upsampling
#if UPSCALING_CONTEXT
					if(do_fancy&&compptr.downsampled_width>2)
					{
						upsample.methods[ci]=h2v2_fancy_upsample;
						upsample.need_context_rows=true;
						compptr.doContext=true;
					}
					else 
#endif
						upsample.methods[ci]=h2v2_upsample;
				}
				else if((h_out_group%h_in_group)==0&&(v_out_group%v_in_group)==0)
				{
					// Generic integral-factors upsampling method
					upsample.methods[ci]=int_upsample;
					upsample.h_expand[ci]=(byte)(h_out_group/h_in_group);
					upsample.v_expand[ci]=(byte)(v_out_group/v_in_group);
				}
				else ERREXIT(cinfo, J_MESSAGE_CODE.JERR_FRACT_SAMPLE_NOTIMPL);

				if(need_buffer)
				{
					upsample.color_buf[ci]=alloc_sarray(cinfo, (uint)jround_up((int)cinfo.output_width, (int)cinfo.max_h_samp_factor), (uint)cinfo.max_v_samp_factor);
				}
			}
		}