Esempio n. 1
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));
                }
            }
        }
Esempio n. 2
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;
            }
        }
Esempio n. 3
0
        // Adobe-style YCCK->CMYK conversion.
        // We convert YCbCr to R=1-C, G=1-M, and B=1-Y using the same
        // conversion as above, while passing K (black) unchanged.
        // We assume build_ycc_rgb_table has been called.
        static void ycck_cmyk_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];
                byte[] inptr3 = input_buf[3][input_row];
                input_row++;
                byte[] outptr     = output_buf[output_row++];
                int    outptr_ind = 0;
                for (uint col = 0; col < num_cols; col++)
                {
                    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 = MAXJSAMPLE - (y + Crrtab[cr]);                                  // red
                    outptr[outptr_ind++] = (byte)(tmp >= MAXJSAMPLE?MAXJSAMPLE:(tmp < 0?0:tmp));
                    tmp = MAXJSAMPLE - (y + ((int)((Cbgtab[cb] + Crgtab[cr]) >> SCALEBITS))); // green
                    outptr[outptr_ind++] = (byte)(tmp >= MAXJSAMPLE?MAXJSAMPLE:(tmp < 0?0:tmp));
                    tmp = MAXJSAMPLE - (y + Cbbtab[cb]);                                      // blue
                    outptr[outptr_ind++] = (byte)(tmp >= MAXJSAMPLE?MAXJSAMPLE:(tmp < 0?0:tmp));

                    // K passes through unchanged
                    outptr[outptr_ind++] = inptr3[col];
                }
            }
        }
Esempio n. 4
0
        // Module initialization routine for output colorspace conversion.
        public static void jinit_color_deconverter(jpeg_decompress cinfo)
        {
            my_color_deconverter cconvert = null;

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

            cinfo.cconvert      = cconvert;
            cconvert.start_pass = start_pass_dcolor;

            // Make sure num_components agrees with jpeg_color_space
            switch (cinfo.jpeg_color_space)
            {
            case J_COLOR_SPACE.JCS_GRAYSCALE: if (cinfo.num_components != 1)
                {
                    ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_J_COLORSPACE);
                }
                break;

            case J_COLOR_SPACE.JCS_RGB:
            case J_COLOR_SPACE.JCS_YCbCr: if (cinfo.num_components != 3)
                {
                    ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_J_COLORSPACE);
                }
                break;

            case J_COLOR_SPACE.JCS_CMYK:
            case J_COLOR_SPACE.JCS_YCCK: if (cinfo.num_components != 4)
                {
                    ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_J_COLORSPACE);
                }
                break;

            default: if (cinfo.num_components < 1)
                {
                    ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_J_COLORSPACE);
                }
                break;                                                                                                           // JCS_UNKNOWN can be anything
            }

            // Set out_color_components and conversion method based on requested space.
            // Also clear the component_needed flags for any unused components,
            // so that earlier pipeline stages can avoid useless computation.
            switch (cinfo.out_color_space)
            {
            case J_COLOR_SPACE.JCS_GRAYSCALE:
                cinfo.out_color_components = 1;
                if (cinfo.jpeg_color_space == J_COLOR_SPACE.JCS_GRAYSCALE || cinfo.jpeg_color_space == J_COLOR_SPACE.JCS_YCbCr)
                {
                    cconvert.color_convert = grayscale_convert;
                    // For color->grayscale conversion, only the Y (0) component is needed
                    for (int ci = 1; ci < cinfo.num_components; ci++)
                    {
                        cinfo.comp_info[ci].component_needed = false;
                    }
                }
                else
                {
                    ERREXIT(cinfo, J_MESSAGE_CODE.JERR_CONVERSION_NOTIMPL);
                }
                break;

            case J_COLOR_SPACE.JCS_RGB:
                cinfo.out_color_components = RGB_PIXELSIZE;
                if (cinfo.jpeg_color_space == J_COLOR_SPACE.JCS_YCbCr)
                {
                    cconvert.color_convert = ycc_rgb_convert;
                    build_ycc_rgb_table(cinfo);
                }
                else if (cinfo.jpeg_color_space == J_COLOR_SPACE.JCS_GRAYSCALE)
                {
                    cconvert.color_convert = gray_rgb_convert;
                }
                else if (cinfo.jpeg_color_space == J_COLOR_SPACE.JCS_RGB && RGB_PIXELSIZE == 3)
                {
                    cconvert.color_convert = null_convert;
                }
                else
                {
                    ERREXIT(cinfo, J_MESSAGE_CODE.JERR_CONVERSION_NOTIMPL);
                }
                break;

            case J_COLOR_SPACE.JCS_CMYK:
                cinfo.out_color_components = 4;
                if (cinfo.jpeg_color_space == J_COLOR_SPACE.JCS_YCCK)
                {
                    cconvert.color_convert = ycck_cmyk_convert;
                    build_ycc_rgb_table(cinfo);
                }
                else if (cinfo.jpeg_color_space == J_COLOR_SPACE.JCS_CMYK)
                {
                    cconvert.color_convert = null_convert;
                }
                else
                {
                    ERREXIT(cinfo, J_MESSAGE_CODE.JERR_CONVERSION_NOTIMPL);
                }
                break;

            default:
                // Permit null conversion to same output space
                if (cinfo.out_color_space == cinfo.jpeg_color_space)
                {
                    cinfo.out_color_components = cinfo.num_components;
                    cconvert.color_convert     = null_convert;
                }
                else
                {
                    ERREXIT(cinfo, J_MESSAGE_CODE.JERR_CONVERSION_NOTIMPL);                          // unsupported non-null conversion
                }
                break;
            }

            if (cinfo.quantize_colors)
            {
                cinfo.output_components = 1;                                 // single colormapped output component
            }
            else
            {
                cinfo.output_components = cinfo.out_color_components;
            }
        }
Esempio n. 5
0
		// Module initialization routine for output colorspace conversion.
		public static void jinit_color_deconverter(jpeg_decompress cinfo)
		{
			my_color_deconverter cconvert=null;

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

			cinfo.cconvert=cconvert;
			cconvert.start_pass=start_pass_dcolor;

			// Make sure num_components agrees with jpeg_color_space
			switch(cinfo.jpeg_color_space)
			{
				case J_COLOR_SPACE.JCS_GRAYSCALE: if(cinfo.num_components!=1) ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_J_COLORSPACE); break;
				case J_COLOR_SPACE.JCS_RGB:
				case J_COLOR_SPACE.JCS_YCbCr: if(cinfo.num_components!=3) ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_J_COLORSPACE); break;
				case J_COLOR_SPACE.JCS_CMYK:
				case J_COLOR_SPACE.JCS_YCCK: if(cinfo.num_components!=4) ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_J_COLORSPACE); break;
				default: if(cinfo.num_components<1) ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_J_COLORSPACE); break; // JCS_UNKNOWN can be anything
			}

			// Set out_color_components and conversion method based on requested space.
			// Also clear the component_needed flags for any unused components,
			// so that earlier pipeline stages can avoid useless computation.
			switch(cinfo.out_color_space)
			{
				case J_COLOR_SPACE.JCS_GRAYSCALE:
					cinfo.out_color_components=1;
					if(cinfo.jpeg_color_space==J_COLOR_SPACE.JCS_GRAYSCALE||cinfo.jpeg_color_space==J_COLOR_SPACE.JCS_YCbCr)
					{
						cconvert.color_convert=grayscale_convert;
						// For color->grayscale conversion, only the Y (0) component is needed
						for(int ci=1; ci<cinfo.num_components; ci++) cinfo.comp_info[ci].component_needed=false;
					}
					else ERREXIT(cinfo, J_MESSAGE_CODE.JERR_CONVERSION_NOTIMPL);
					break;
				case J_COLOR_SPACE.JCS_RGB:
					cinfo.out_color_components=RGB_PIXELSIZE;
					if(cinfo.jpeg_color_space==J_COLOR_SPACE.JCS_YCbCr)
					{
						cconvert.color_convert=ycc_rgb_convert;
						build_ycc_rgb_table(cinfo);
					}
					else if(cinfo.jpeg_color_space==J_COLOR_SPACE.JCS_GRAYSCALE)
					{
						cconvert.color_convert=gray_rgb_convert;
					}
					else if(cinfo.jpeg_color_space==J_COLOR_SPACE.JCS_RGB&&RGB_PIXELSIZE==3) cconvert.color_convert=null_convert;
					else ERREXIT(cinfo, J_MESSAGE_CODE.JERR_CONVERSION_NOTIMPL);
					break;
				case J_COLOR_SPACE.JCS_CMYK:
					cinfo.out_color_components=4;
					if(cinfo.jpeg_color_space==J_COLOR_SPACE.JCS_YCCK)
					{
						cconvert.color_convert=ycck_cmyk_convert;
						build_ycc_rgb_table(cinfo);
					}
					else if(cinfo.jpeg_color_space==J_COLOR_SPACE.JCS_CMYK) cconvert.color_convert=null_convert;
					else ERREXIT(cinfo, J_MESSAGE_CODE.JERR_CONVERSION_NOTIMPL);
					break;
				default:
					// Permit null conversion to same output space
					if(cinfo.out_color_space==cinfo.jpeg_color_space)
					{
						cinfo.out_color_components=cinfo.num_components;
						cconvert.color_convert=null_convert;
					}
					else ERREXIT(cinfo, J_MESSAGE_CODE.JERR_CONVERSION_NOTIMPL); // unsupported non-null conversion
					break;
			}

			if(cinfo.quantize_colors) cinfo.output_components=1; // single colormapped output component
			else cinfo.output_components=cinfo.out_color_components;
		}