示例#1
0
        // Initialize FDCT manager.
        static void jinit_forward_dct(jpeg_compress cinfo)
        {
            jpeg_lossy_c_codec lossyc = (jpeg_lossy_c_codec)cinfo.coef;
            fdct_controller    fdct   = null;

            try
            {
                fdct = new fdct_controller();
            }
            catch
            {
                ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_OUT_OF_MEMORY, 4);
            }
            lossyc.fdct_private    = fdct;
            lossyc.fdct_start_pass = start_pass_fdctmgr;

            fdct.do_dct             = jpeg_fdct_ifast;
            lossyc.fdct_forward_DCT = forward_DCT;

#if DCT_FLOAT_SUPPORTED
            fdct.do_float_dct = jpeg_fdct_float;
            if (cinfo.useFloatDCT)
            {
                lossyc.fdct_forward_DCT = forward_DCT_float;
            }
#endif
            // Mark divisor tables unallocated
            for (int i = 0; i < NUM_QUANT_TBLS; i++)
            {
                fdct.divisors[i] = null;
#if DCT_FLOAT_SUPPORTED
                fdct.float_divisors[i] = null;
#endif
            }
        }
示例#2
0
        // This version is used for floating-point DCT implementations.
        static void forward_DCT_float(jpeg_compress cinfo, jpeg_component_info compptr, byte[][] sample_data, short[][] coef_blocks, int coef_offset, uint start_row, uint start_col, uint num_blocks)
        {
            // This routine is heavily used, so it's worth coding it tightly
            jpeg_lossy_c_codec lossyc = (jpeg_lossy_c_codec)cinfo.coef;
            fdct_controller    fdct   = (fdct_controller)lossyc.fdct_private;

            float_DCT_method_ptr do_dct = fdct.do_float_dct;

            double[] divisors  = fdct.float_divisors[compptr.quant_tbl_no];
            double[] workspace = new double[DCTSIZE2];                  // work area for FDCT subroutine

            for (int bi = 0; bi < num_blocks; bi++, start_col += DCTSIZE)
            {
                // Load data into workspace, applying unsigned->signed conversion
                int wsptr = 0;
                for (int elemr = 0; elemr < DCTSIZE; elemr++)
                {
                    byte[] elem = sample_data[start_row + elemr];
                    uint   eptr = start_col;

                    // unroll the inner loop
                    workspace[wsptr++] = elem[eptr++] - CENTERJSAMPLE;
                    workspace[wsptr++] = elem[eptr++] - CENTERJSAMPLE;
                    workspace[wsptr++] = elem[eptr++] - CENTERJSAMPLE;
                    workspace[wsptr++] = elem[eptr++] - CENTERJSAMPLE;
                    workspace[wsptr++] = elem[eptr++] - CENTERJSAMPLE;
                    workspace[wsptr++] = elem[eptr++] - CENTERJSAMPLE;
                    workspace[wsptr++] = elem[eptr++] - CENTERJSAMPLE;
                    workspace[wsptr++] = elem[eptr++] - CENTERJSAMPLE;
                }

                // Perform the DCT
                do_dct(workspace);

                // Quantize/descale the coefficients, and store into coef_blocks[]
                //old short[] output_ptr=coef_blocks[coef_offset][bi];
                short[] output_ptr = coef_blocks[coef_offset + bi];

                for (int i = 0; i < DCTSIZE2; i++)
                {
                    // Apply the quantization and scaling factor
                    double temp = workspace[i] * divisors[i];

                    // Round to nearest integer.
                    // Since C does not specify the direction of rounding for negative
                    // quotients, we have to force the dividend positive for portability.
                    // The maximum coefficient size is +-16K (for 12-bit data), so this
                    // code should work for either 16-bit or 32-bit ints.
                    output_ptr[i] = (short)((int)(temp + 16384.5) - 16384);
                }
            }
        }
示例#3
0
		// Initialize FDCT manager.
		static void jinit_forward_dct(jpeg_compress cinfo)
		{
			jpeg_lossy_c_codec lossyc=(jpeg_lossy_c_codec)cinfo.coef;
			fdct_controller fdct=null;

			try
			{
				fdct=new fdct_controller();
			}
			catch
			{
				ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_OUT_OF_MEMORY, 4);
			}
			lossyc.fdct_private=fdct;
			lossyc.fdct_start_pass=start_pass_fdctmgr;

			fdct.do_dct=jpeg_fdct_ifast;
			lossyc.fdct_forward_DCT=forward_DCT;

#if DCT_FLOAT_SUPPORTED
			fdct.do_float_dct=jpeg_fdct_float;
			if(cinfo.useFloatDCT) lossyc.fdct_forward_DCT=forward_DCT_float;
#endif
			// Mark divisor tables unallocated
			for(int i=0; i<NUM_QUANT_TBLS; i++)
			{
				fdct.divisors[i]=null;
#if DCT_FLOAT_SUPPORTED
				fdct.float_divisors[i]=null;
#endif
			}
		}
示例#4
0
        public static uint jpeg_write_image(jpeg_compress cinfo, byte[] image, bool swapChannels, bool alpha)
        {
            if (cinfo.input_components != 3 || cinfo.lossless || cinfo.in_color_space != J_COLOR_SPACE.JCS_RGB ||
                cinfo.num_components != 3 || cinfo.jpeg_color_space != J_COLOR_SPACE.JCS_YCbCr ||
                cinfo.data_precision != 8 || cinfo.DCT_size != 8 || cinfo.block_in_MCU != 3 || cinfo.arith_code ||
                cinfo.max_h_samp_factor != 1 || cinfo.max_v_samp_factor != 1 || cinfo.next_scanline != 0 || cinfo.num_scans != 1)
            {
                throw new Exception();
            }

            if (cinfo.global_state != STATE.CSCANNING)
            {
                ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_BAD_STATE, cinfo.global_state);
            }

            // Give master control module another chance if this is first call to
            // jpeg_write_scanlines. This lets output of the frame/scan headers be
            // delayed so that application can write COM, etc, markers between
            // jpeg_start_compress and jpeg_write_scanlines.
            if (cinfo.master.call_pass_startup)
            {
                cinfo.master.pass_startup(cinfo);
            }

            jpeg_lossy_c_codec lossyc = (jpeg_lossy_c_codec)cinfo.coef;
            c_coef_controller  coef   = (c_coef_controller)lossyc.coef_private;
            fdct_controller    fdct   = (fdct_controller)lossyc.fdct_private;

            double[] workspaceY  = new double[DCTSIZE2];
            double[] workspaceCr = new double[DCTSIZE2];
            double[] workspaceCb = new double[DCTSIZE2];

            short[][] coefs = new short[][] { new short[DCTSIZE2], new short[DCTSIZE2], new short[DCTSIZE2] };

            short[] coefY  = coefs[0];
            short[] coefCb = coefs[1];
            short[] coefCr = coefs[2];

            double[] divisorY = fdct.float_divisors[0];
            double[] divisorC = fdct.float_divisors[1];

            int bpp = alpha?4:3;

            for (int y = 0; y < (cinfo.image_height + DCTSIZE - 1) / DCTSIZE; y++)
            {
                int yFormImage = Math.Min((int)cinfo.image_height - y * DCTSIZE, DCTSIZE);
                for (int x = 0; x < (cinfo.image_width + DCTSIZE - 1) / DCTSIZE; x++)
                {
                    int xFormImage   = Math.Min((int)cinfo.image_width - x * DCTSIZE, DCTSIZE);
                    int workspacepos = 0;
                    for (int j = 0; j < yFormImage; j++)
                    {
                        int imagepos = ((y * DCTSIZE + j) * (int)cinfo.image_width + x * DCTSIZE) * bpp;
                        for (int i = 0; i < xFormImage; i++, workspacepos++)
                        {
                            byte r = image[imagepos++];
                            byte g = image[imagepos++];
                            byte b = image[imagepos++];
                            if (alpha)
                            {
                                imagepos++;
                            }

                            if (!swapChannels)
                            {
                                workspaceY[workspacepos]  = 0.299 * r + 0.587 * g + 0.114 * b - CENTERJSAMPLE;
                                workspaceCb[workspacepos] = -0.168736 * r - 0.331264 * g + 0.5 * b;
                                workspaceCr[workspacepos] = 0.5 * r - 0.418688 * g - 0.081312 * b;
                            }
                            else
                            {
                                workspaceY[workspacepos]  = 0.299 * b + 0.587 * g + 0.114 * r - CENTERJSAMPLE;
                                workspaceCb[workspacepos] = -0.168736 * b - 0.331264 * g + 0.5 * r;
                                workspaceCr[workspacepos] = 0.5 * b - 0.418688 * g - 0.081312 * r;
                            }
                        }

                        int lastworkspacepos = workspacepos - 1;
                        for (int i = xFormImage; i < DCTSIZE; i++, workspacepos++)
                        {
                            workspaceY[workspacepos]  = workspaceY[lastworkspacepos];
                            workspaceCb[workspacepos] = workspaceCb[lastworkspacepos];
                            workspaceCr[workspacepos] = workspaceCr[lastworkspacepos];
                        }
                    }

                    int lastworkspacelinepos = (yFormImage - 1) * DCTSIZE;
                    for (int j = yFormImage; j < DCTSIZE; j++)
                    {
                        int lastworkspacepos = lastworkspacelinepos;
                        for (int i = 0; i < DCTSIZE; i++, workspacepos++, lastworkspacepos++)
                        {
                            workspaceY[workspacepos]  = workspaceY[lastworkspacepos];
                            workspaceCb[workspacepos] = workspaceCb[lastworkspacepos];
                            workspaceCr[workspacepos] = workspaceCr[lastworkspacepos];
                        }
                    }

                    // ein block (3 componenten)
                    jpeg_fdct_float(workspaceY);
                    jpeg_fdct_float(workspaceCb);
                    jpeg_fdct_float(workspaceCr);

                    for (int i = 0; i < DCTSIZE2; i++)
                    {
                        // Apply the quantization and scaling factor
                        double tempY  = workspaceY[i] * divisorY[i];
                        double tempCb = workspaceCb[i] * divisorC[i];
                        double tempCr = workspaceCr[i] * divisorC[i];

                        // Round to nearest integer.
                        // Since C does not specify the direction of rounding for negative
                        // quotients, we have to force the dividend positive for portability.
                        // The maximum coefficient size is +-16K (for 12-bit data), so this
                        // code should work for either 16-bit or 32-bit ints.
                        coefY[i]  = (short)((int)(tempY + 16384.5) - 16384);
                        coefCb[i] = (short)((int)(tempCb + 16384.5) - 16384);
                        coefCr[i] = (short)((int)(tempCr + 16384.5) - 16384);
                    }

                    lossyc.entropy_encode_mcu(cinfo, coefs);
                }
            }

            cinfo.next_scanline = cinfo.image_height;
            return(cinfo.image_height);
        }
示例#5
0
        // Initialize for a processing pass.
        // Verify that all referenced Q-tables are present, and set up
        // the divisor table for each one.
        // In the current implementation, DCT of all components is done during
        // the first pass, even if only some components will be output in the
        // first scan. Hence all components should be examined here.
        static void start_pass_fdctmgr(jpeg_compress cinfo)
        {
            jpeg_lossy_c_codec lossyc = (jpeg_lossy_c_codec)cinfo.coef;
            fdct_controller    fdct   = (fdct_controller)lossyc.fdct_private;

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

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

                JQUANT_TBL qtbl = cinfo.quant_tbl_ptrs[qtblno];

                // Compute divisors for this quant table
                // We may do this more than once for same table, but it's not a big deal
                if (fdct.divisors[qtblno] == null)
                {
                    try
                    {
                        fdct.divisors[qtblno] = new int[DCTSIZE2];
                    }
                    catch
                    {
                        ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_OUT_OF_MEMORY, 4);
                    }
                }

                int[] dtbl = fdct.divisors[qtblno];
                for (int i = 0; i < DCTSIZE2; i++)
                {
                    dtbl[i] = ((int)qtbl.quantval[i] * aanscales[i] + 1024) >> 11;
                }

#if DCT_FLOAT_SUPPORTED
                if (fdct.float_divisors[qtblno] == null)
                {
                    try
                    {
                        fdct.float_divisors[qtblno] = new double[DCTSIZE2];
                    }
                    catch
                    {
                        ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_OUT_OF_MEMORY, 4);
                    }
                }

                double[] fdtbl = fdct.float_divisors[qtblno];
                int      di    = 0;
                for (int row = 0; row < DCTSIZE; row++)
                {
                    for (int col = 0; col < DCTSIZE; col++)
                    {
                        fdtbl[di] = 1.0 / (qtbl.quantval[di] * aanscalefactor[row] * aanscalefactor[col] * 8.0);
                        di++;
                    }
                }
#endif
            }
        }
示例#6
0
        // Perform forward DCT on one or more blocks of a component.
        //
        // The input samples are taken from the sample_data[] array starting at
        // position start_row/start_col, and moving to the right for any additional
        // blocks. The quantized coefficients are returned in coef_blocks[].

        // This version is used for integer DCT implementations.
        static void forward_DCT(jpeg_compress cinfo, jpeg_component_info compptr, byte[][] sample_data, short[][] coef_blocks, int coef_offset, uint start_row, uint start_col, uint num_blocks)
        {
            // This routine is heavily used, so it's worth coding it tightly
            jpeg_lossy_c_codec lossyc = (jpeg_lossy_c_codec)cinfo.coef;
            fdct_controller    fdct   = (fdct_controller)lossyc.fdct_private;

            forward_DCT_method_ptr do_dct = fdct.do_dct;

            int[] divisors  = fdct.divisors[compptr.quant_tbl_no];
            int[] workspace = new int[DCTSIZE2];                // work area for FDCT subroutine

            for (int bi = 0; bi < num_blocks; bi++, start_col += DCTSIZE)
            {
                // Load data into workspace, applying unsigned->signed conversion
                int wsptr = 0;
                for (int elemr = 0; elemr < DCTSIZE; elemr++)
                {
                    byte[] elem = sample_data[start_row + elemr];
                    uint   eptr = start_col;

                    // unroll the inner loop
                    workspace[wsptr++] = elem[eptr++] - CENTERJSAMPLE;
                    workspace[wsptr++] = elem[eptr++] - CENTERJSAMPLE;
                    workspace[wsptr++] = elem[eptr++] - CENTERJSAMPLE;
                    workspace[wsptr++] = elem[eptr++] - CENTERJSAMPLE;
                    workspace[wsptr++] = elem[eptr++] - CENTERJSAMPLE;
                    workspace[wsptr++] = elem[eptr++] - CENTERJSAMPLE;
                    workspace[wsptr++] = elem[eptr++] - CENTERJSAMPLE;
                    workspace[wsptr++] = elem[eptr++] - CENTERJSAMPLE;
                }

                // Perform the DCT
                do_dct(workspace);

                // Quantize/descale the coefficients, and store into coef_blocks[]
                //old short[] output_ptr=coef_blocks[coef_offset][bi];
                short[] output_ptr = coef_blocks[coef_offset + bi];

                for (int i = 0; i < DCTSIZE2; i++)
                {
                    int qval = divisors[i];
                    int temp = workspace[i];
                    // Divide the coefficient value by qval, ensuring proper rounding.
                    // Since C does not specify the direction of rounding for negative
                    // quotients, we have to force the dividend positive for portability.
                    if (temp < 0)
                    {
                        temp  = -temp;
                        temp += qval >> 1;                      // for rounding
                        temp /= qval;
                        temp  = -temp;
                    }
                    else
                    {
                        temp += qval >> 1;                      // for rounding
                        temp /= qval;
                    }
                    output_ptr[i] = (short)temp;
                }
            }
        }