Beispiel #1
0
        // Support routine: generate one scan for specified component
        static int fill_a_scan(jpeg_scan_info[] scanptr, int scanptr_ind, int ci, int Ss, int Se, int Ah, int Al)
        {
            jpeg_scan_info scan = scanptr[scanptr_ind];

            scan.comps_in_scan      = 1;
            scan.component_index[0] = ci;
            scan.Ss = Ss;
            scan.Se = Se;
            scan.Ah = Ah;
            scan.Al = Al;
            scanptr_ind++;
            return(scanptr_ind);
        }
Beispiel #2
0
        // Set up the scan parameters for the current scan
        static void select_scan_parameters(jpeg_compress cinfo)
        {
#if NEED_SCAN_SCRIPT
            if (cinfo.scan_info != null)
            {
                // Prepare for current scan --- the script is already validated
                my_comp_master master  = (my_comp_master)cinfo.master;
                jpeg_scan_info scanptr = cinfo.scan_info[master.scan_number];

                cinfo.comps_in_scan = scanptr.comps_in_scan;
                for (int ci = 0; ci < scanptr.comps_in_scan; ci++)
                {
                    cinfo.cur_comp_info[ci] = cinfo.comp_info[scanptr.component_index[ci]];
                }
                cinfo.Ss = scanptr.Ss;
                cinfo.Se = scanptr.Se;
                cinfo.Ah = scanptr.Ah;
                cinfo.Al = scanptr.Al;
            }
            else
#endif
            {
                // Prepare for single sequential-JPEG scan containing all components
                if (cinfo.num_components > MAX_COMPS_IN_SCAN)
                {
                    ERREXIT2(cinfo, J_MESSAGE_CODE.JERR_COMPONENT_COUNT, cinfo.num_components, MAX_COMPS_IN_SCAN);
                }
                cinfo.comps_in_scan = cinfo.num_components;
                for (int ci = 0; ci < cinfo.num_components; ci++)
                {
                    cinfo.cur_comp_info[ci] = cinfo.comp_info[ci];
                }
                if (cinfo.lossless)
                {
#if C_LOSSLESS_SUPPORTED
                    // If we fall through to here, the user specified lossless, but did not
                    // provide a scan script.
                    ERREXIT(cinfo, J_MESSAGE_CODE.JERR_NO_LOSSLESS_SCRIPT);
#endif
                }
                else
                {
                    cinfo.process = J_CODEC_PROCESS.JPROC_SEQUENTIAL;
                    cinfo.Ss      = 0;
                    cinfo.Se      = DCTSIZE2 - 1;
                    cinfo.Ah      = 0;
                    cinfo.Al      = 0;
                }
            }
        }
Beispiel #3
0
 // Support routine: generate one scan for each component
 static int fill_scans(jpeg_scan_info[] scanptr, int scanptr_ind, int ncomps, int Ss, int Se, int Ah, int Al)
 {
     for (int ci = 0; ci < ncomps; ci++)
     {
         jpeg_scan_info scan = scanptr[scanptr_ind];
         scan.comps_in_scan      = 1;
         scan.component_index[0] = ci;
         scan.Ss = Ss;
         scan.Se = Se;
         scan.Ah = Ah;
         scan.Al = Al;
         scanptr_ind++;
     }
     return(scanptr_ind);
 }
Beispiel #4
0
 // Support routine: generate interleaved DC scan if possible, else N scans
 static int fill_dc_scans(jpeg_scan_info[] scanptr, int scanptr_ind, int ncomps, int Ah, int Al)
 {
     if (ncomps <= MAX_COMPS_IN_SCAN)
     {
         jpeg_scan_info scan = scanptr[scanptr_ind];
         // Single interleaved DC scan
         scan.comps_in_scan = ncomps;
         for (int ci = 0; ci < ncomps; ci++)
         {
             scan.component_index[ci] = ci;
         }
         scan.Ss = scan.Se = 0;
         scan.Ah = Ah;
         scan.Al = Al;
         scanptr_ind++;
     }
     else
     {
         // Noninterleaved DC scan for each component
         scanptr_ind = fill_scans(scanptr, scanptr_ind, ncomps, 0, 0, Ah, Al);
     }
     return(scanptr_ind);
 }
Beispiel #5
0
		// Support routine: generate interleaved DC scan if possible, else N scans
		static int fill_dc_scans(jpeg_scan_info[] scanptr, int scanptr_ind, int ncomps, int Ah, int Al)
		{
			if(ncomps<=MAX_COMPS_IN_SCAN)
			{
				jpeg_scan_info scan=scanptr[scanptr_ind];
				// Single interleaved DC scan
				scan.comps_in_scan=ncomps;
				for(int ci=0; ci<ncomps; ci++) scan.component_index[ci]=ci;
				scan.Ss=scan.Se=0;
				scan.Ah=Ah;
				scan.Al=Al;
				scanptr_ind++;
			}
			else
			{
				// Noninterleaved DC scan for each component
				scanptr_ind=fill_scans(scanptr, scanptr_ind, ncomps, 0, 0, Ah, Al);
			}
			return scanptr_ind;
		}
Beispiel #6
0
		// Support routine: generate one scan for specified component
		static int fill_a_scan(jpeg_scan_info[] scanptr, int scanptr_ind, int ci, int Ss, int Se, int Ah, int Al)
		{
			jpeg_scan_info scan=scanptr[scanptr_ind];
			scan.comps_in_scan=1;
			scan.component_index[0]=ci;
			scan.Ss=Ss;
			scan.Se=Se;
			scan.Ah=Ah;
			scan.Al=Al;
			scanptr_ind++;
			return scanptr_ind;
		}
Beispiel #7
0
		// Support routine: generate one scan for each component
		static int fill_scans(jpeg_scan_info[] scanptr, int scanptr_ind, int ncomps, int Ss, int Se, int Ah, int Al)
		{
			for(int ci=0; ci<ncomps; ci++)
			{
				jpeg_scan_info scan=scanptr[scanptr_ind];
				scan.comps_in_scan=1;
				scan.component_index[0]=ci;
				scan.Ss=Ss;
				scan.Se=Se;
				scan.Ah=Ah;
				scan.Al=Al;
				scanptr_ind++;
			}
			return scanptr_ind;
		}
Beispiel #8
0
        // Create a single-entry lossless-JPEG script containing all components.
        // cinfo.num_components must be correct.
        // predictor: 1..7
        // point_transform: 0..data_precision(usally 8) // reduction of colors
        public static void jpeg_simple_lossless(jpeg_compress cinfo, int predictor, int point_transform)
        {
            int ncomps = cinfo.num_components;

            // Safety check to ensure start_compress not called yet.
            if (cinfo.global_state != STATE.CSTART)
            {
                ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_BAD_STATE, cinfo.global_state);
            }

            cinfo.lossless = true;

            // Set jpeg_color_space.
            jpeg_default_colorspace(cinfo);

            // Check to ensure that all components will fit in one scan.
            if (cinfo.num_components > MAX_COMPS_IN_SCAN)
            {
                ERREXIT2(cinfo, J_MESSAGE_CODE.JERR_COMPONENT_COUNT, cinfo.num_components, MAX_COMPS_IN_SCAN);
            }

            // Allocate space for script.
            // We need to put it in the permanent pool in case the application performs
            // multiple compressions without changing the settings. To avoid a memory
            // leak if jpeg_simple_lossless is called repeatedly for the same JPEG
            // object, we try to re-use previously allocated space.
            int nscans = 1;

            if (cinfo.script_space == null || cinfo.script_space_size < nscans)
            {
                cinfo.script_space_size = nscans;

                try
                {
                    cinfo.script_space = new jpeg_scan_info[cinfo.script_space_size];
                    for (int i = 0; i < cinfo.script_space_size; i++)
                    {
                        cinfo.script_space[i] = new jpeg_scan_info();
                    }
                }
                catch
                {
                    ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_OUT_OF_MEMORY, 4);
                }
            }

            jpeg_scan_info scanptr = cinfo.script_space[0];

            cinfo.scan_info = cinfo.script_space;
            cinfo.num_scans = nscans;

            // Fill the script.
            scanptr.comps_in_scan = ncomps;
            for (int ci = 0; ci < ncomps; ci++)
            {
                scanptr.component_index[ci] = ci;
            }
            scanptr.Ss = predictor;
            scanptr.Se = 0;
            scanptr.Ah = 0;
            scanptr.Al = point_transform;
        }
Beispiel #9
0
        // Verify that the scan script in cinfo.scan_info[] is valid; also
        // determine whether it uses progressive JPEG, and set cinfo.process.
        static void validate_script(jpeg_compress cinfo)
        {
#if C_PROGRESSIVE_SUPPORTED
            int[,] last_bitpos = new int[MAX_COMPONENTS, DCTSIZE2];
            // -1 until that coefficient has been seen; then last Al for it
#endif
            if (cinfo.num_scans <= 0)
            {
                ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_BAD_SCAN_SCRIPT, 0);
            }

#if !C_MULTISCAN_FILES_SUPPORTED
            if (cinfo.num_scans > 1)
            {
                ERREXIT(cinfo, J_MESSAGE_CODE.JERR_NOT_COMPILED);
            }
#endif

            bool[] component_sent = new bool[MAX_COMPONENTS];
            if (cinfo.lossless)
            {
#if C_LOSSLESS_SUPPORTED
                cinfo.process = J_CODEC_PROCESS.JPROC_LOSSLESS;
                for (int ci = 0; ci < cinfo.num_components; ci++)
                {
                    component_sent[ci] = false;
                }
#else
                ERREXIT(cinfo, J_MESSAGE_CODE.JERR_NOT_COMPILED);
#endif
            }
            // For sequential JPEG, all scans must have Ss=0, Se=DCTSIZE2-1;
            // for progressive JPEG, no scan can have this.
            else if (cinfo.scan_info[0].Ss != 0 || cinfo.scan_info[0].Se != DCTSIZE2 - 1)
            {
#if C_PROGRESSIVE_SUPPORTED
                cinfo.process = J_CODEC_PROCESS.JPROC_PROGRESSIVE;
                for (int ci = 0; ci < cinfo.num_components; ci++)
                {
                    for (int coefi = 0; coefi < DCTSIZE2; coefi++)
                    {
                        last_bitpos[ci, coefi] = -1;
                    }
                }
#else
                ERREXIT(cinfo, J_MESSAGE_CODE.JERR_NOT_COMPILED);
#endif
            }
            else
            {
                cinfo.process = J_CODEC_PROCESS.JPROC_SEQUENTIAL;
                for (int ci = 0; ci < cinfo.num_components; ci++)
                {
                    component_sent[ci] = false;
                }
            }

            for (int scanno = 1; scanno <= cinfo.num_scans; scanno++)
            {
                jpeg_scan_info scan_info = cinfo.scan_info[scanno - 1];

                // Validate component indexes
                int ncomps = scan_info.comps_in_scan;
                if (ncomps <= 0 || ncomps > MAX_COMPS_IN_SCAN)
                {
                    ERREXIT2(cinfo, J_MESSAGE_CODE.JERR_COMPONENT_COUNT, ncomps, MAX_COMPS_IN_SCAN);
                }
                for (int ci = 0; ci < ncomps; ci++)
                {
                    int thisi = scan_info.component_index[ci];
                    if (thisi < 0 || thisi >= cinfo.num_components)
                    {
                        ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_BAD_SCAN_SCRIPT, scanno);
                    }

                    // Components must appear in SOF order within each scan
                    if (ci > 0 && thisi <= scan_info.component_index[ci - 1])
                    {
                        ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_BAD_SCAN_SCRIPT, scanno);
                    }
                }

                // Validate progression parameters
                int Ss = scan_info.Ss;
                int Se = scan_info.Se;
                int Ah = scan_info.Ah;
                int Al = scan_info.Al;
                if (cinfo.process == J_CODEC_PROCESS.JPROC_LOSSLESS)
                {
#if C_LOSSLESS_SUPPORTED
                    // The JPEG spec simply gives the range 0..15 for Al (Pt), but that
                    // seems wrong: the upper bound ought to depend on data precision.
                    // Perhaps they really meant 0..N-1 for N-bit precision, which is what
                    // we allow here.
                    if (Ss < 1 || Ss > 7 || Se != 0 || Ah != 0 || Al < 0 || Al >= cinfo.data_precision) // Ss predictor selector; Al point transform
                    {
                        ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_BAD_LOSSLESS_SCRIPT, scanno);
                    }

                    // Make sure components are not sent twice
                    for (int ci = 0; ci < ncomps; ci++)
                    {
                        int thisi = scan_info.component_index[ci];
                        if (component_sent[thisi])
                        {
                            ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_BAD_SCAN_SCRIPT, scanno);
                        }
                        component_sent[thisi] = true;
                    }
#endif
                }
                else if (cinfo.process == J_CODEC_PROCESS.JPROC_PROGRESSIVE)
                {
#if C_PROGRESSIVE_SUPPORTED
                    // The JPEG spec simply gives the ranges 0..13 for Ah and Al, but that
                    // seems wrong: the upper bound ought to depend on data precision.
                    // Perhaps they really meant 0..N+1 for N-bit precision.
                    // Here we allow 0..10 for 8-bit data; Al larger than 10 results in
                    // out-of-range reconstructed DC values during the first DC scan,
                    // which might cause problems for some decoders.
                    const int MAX_AH_AL = 10;
                    if (Ss < 0 || Ss >= DCTSIZE2 || Se < Ss || Se >= DCTSIZE2 ||
                        Ah < 0 || Ah > MAX_AH_AL || Al < 0 || Al > MAX_AH_AL)
                    {
                        ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_BAD_PROG_SCRIPT, scanno);
                    }
                    if (Ss == 0)
                    {
                        if (Se != 0)
                        {
                            ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_BAD_PROG_SCRIPT, scanno);                               // DC and AC together not OK
                        }
                    }
                    else
                    {
                        if (ncomps != 1)
                        {
                            ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_BAD_PROG_SCRIPT, scanno);                                   // AC scans must be for only one component
                        }
                    }

                    for (int ci = 0; ci < ncomps; ci++)
                    {
                        int comp_ind = scan_info.component_index[ci];
                        if (Ss != 0 && last_bitpos[comp_ind, 0] < 0)
                        {
                            ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_BAD_PROG_SCRIPT, scanno);                                                           // AC without prior DC scan
                        }
                        for (int coefi = Ss; coefi <= Se; coefi++)
                        {
                            if (last_bitpos[comp_ind, coefi] < 0)
                            {                             // first scan of this coefficient
                                if (Ah != 0)
                                {
                                    ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_BAD_PROG_SCRIPT, scanno);
                                }
                            }
                            else
                            {                             // not first scan
                                if (Ah != last_bitpos[comp_ind, coefi] || Al != Ah - 1)
                                {
                                    ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_BAD_PROG_SCRIPT, scanno);
                                }
                            }
                            last_bitpos[comp_ind, coefi] = Al;
                        }
                    }
#endif // C_PROGRESSIVE_SUPPORTED
                }
                else
                {
                    // For sequential JPEG, all progression parameters must be these:
                    if (Ss != 0 || Se != DCTSIZE2 - 1 || Ah != 0 || Al != 0)
                    {
                        ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_BAD_PROG_SCRIPT, scanno);
                    }

                    // Make sure components are not sent twice
                    for (int ci = 0; ci < ncomps; ci++)
                    {
                        int thisi = scan_info.component_index[ci];
                        if (component_sent[thisi])
                        {
                            ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_BAD_SCAN_SCRIPT, scanno);
                        }
                        component_sent[thisi] = true;
                    }
                }
            }             // for(...)

            // Now verify that everything got sent.
            if (cinfo.process == J_CODEC_PROCESS.JPROC_PROGRESSIVE)
            {
#if C_PROGRESSIVE_SUPPORTED
                // For progressive mode, we only check that at least some DC data
                // got sent for each component; the spec does not require that all bits
                // of all coefficients be transmitted. Would it be wiser to enforce
                // transmission of all coefficient bits??
                for (int ci = 0; ci < cinfo.num_components; ci++)
                {
                    if (last_bitpos[ci, 0] < 0)
                    {
                        ERREXIT(cinfo, J_MESSAGE_CODE.JERR_MISSING_DATA);
                    }
                }
#endif
            }
            else
            {
                for (int ci = 0; ci < cinfo.num_components; ci++)
                {
                    if (!component_sent[ci])
                    {
                        ERREXIT(cinfo, J_MESSAGE_CODE.JERR_MISSING_DATA);
                    }
                }
            }
        }