Doxygen Source Code Documentation
        
Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Search   
jcmaster.c
Go to the documentation of this file.00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 #define JPEG_INTERNALS
00015 #include "jinclude.h"
00016 #include "jpeglib.h"
00017 
00018 
00019 
00020 
00021 typedef enum {
00022         main_pass,              
00023         huff_opt_pass,          
00024         output_pass             
00025 } c_pass_type;
00026 
00027 typedef struct {
00028   struct jpeg_comp_master pub;  
00029 
00030   c_pass_type pass_type;        
00031 
00032   int pass_number;              
00033   int total_passes;             
00034 
00035   int scan_number;              
00036 } my_comp_master;
00037 
00038 typedef my_comp_master * my_master_ptr;
00039 
00040 
00041 
00042 
00043 
00044 
00045 LOCAL(void)
00046 initial_setup (j_compress_ptr cinfo)
00047 
00048 {
00049   int ci;
00050   jpeg_component_info *compptr;
00051   long samplesperrow;
00052   JDIMENSION jd_samplesperrow;
00053 
00054   
00055   if (cinfo->image_height <= 0 || cinfo->image_width <= 0
00056       || cinfo->num_components <= 0 || cinfo->input_components <= 0)
00057     ERREXIT(cinfo, JERR_EMPTY_IMAGE);
00058 
00059   
00060   if ((long) cinfo->image_height > (long) JPEG_MAX_DIMENSION ||
00061       (long) cinfo->image_width > (long) JPEG_MAX_DIMENSION)
00062     ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION);
00063 
00064   
00065   samplesperrow = (long) cinfo->image_width * (long) cinfo->input_components;
00066   jd_samplesperrow = (JDIMENSION) samplesperrow;
00067   if ((long) jd_samplesperrow != samplesperrow)
00068     ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
00069 
00070   
00071   if (cinfo->data_precision != BITS_IN_JSAMPLE)
00072     ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
00073 
00074   
00075   if (cinfo->num_components > MAX_COMPONENTS)
00076     ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components,
00077              MAX_COMPONENTS);
00078 
00079   
00080   cinfo->max_h_samp_factor = 1;
00081   cinfo->max_v_samp_factor = 1;
00082   for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
00083        ci++, compptr++) {
00084     if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR ||
00085         compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR)
00086       ERREXIT(cinfo, JERR_BAD_SAMPLING);
00087     cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor,
00088                                    compptr->h_samp_factor);
00089     cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor,
00090                                    compptr->v_samp_factor);
00091   }
00092 
00093   
00094   for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
00095        ci++, compptr++) {
00096     
00097     compptr->component_index = ci;
00098     
00099     compptr->DCT_scaled_size = DCTSIZE;
00100     
00101     compptr->width_in_blocks = (JDIMENSION)
00102       jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor,
00103                     (long) (cinfo->max_h_samp_factor * DCTSIZE));
00104     compptr->height_in_blocks = (JDIMENSION)
00105       jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor,
00106                     (long) (cinfo->max_v_samp_factor * DCTSIZE));
00107     
00108     compptr->downsampled_width = (JDIMENSION)
00109       jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor,
00110                     (long) cinfo->max_h_samp_factor);
00111     compptr->downsampled_height = (JDIMENSION)
00112       jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor,
00113                     (long) cinfo->max_v_samp_factor);
00114     
00115     compptr->component_needed = TRUE;
00116   }
00117 
00118   
00119 
00120 
00121   cinfo->total_iMCU_rows = (JDIMENSION)
00122     jdiv_round_up((long) cinfo->image_height,
00123                   (long) (cinfo->max_v_samp_factor*DCTSIZE));
00124 }
00125 
00126 
00127 #ifdef C_MULTISCAN_FILES_SUPPORTED
00128 
00129 LOCAL(void)
00130 validate_script (j_compress_ptr cinfo)
00131 
00132 
00133 
00134 {
00135   const jpeg_scan_info * scanptr;
00136   int scanno, ncomps, ci, coefi, thisi;
00137   int Ss, Se, Ah, Al;
00138   boolean component_sent[MAX_COMPONENTS];
00139 #ifdef C_PROGRESSIVE_SUPPORTED
00140   int * last_bitpos_ptr;
00141   int last_bitpos[MAX_COMPONENTS][DCTSIZE2];
00142   
00143 #endif
00144 
00145   if (cinfo->num_scans <= 0)
00146     ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, 0);
00147 
00148   
00149 
00150 
00151   scanptr = cinfo->scan_info;
00152   if (scanptr->Ss != 0 || scanptr->Se != DCTSIZE2-1) {
00153 #ifdef C_PROGRESSIVE_SUPPORTED
00154     cinfo->progressive_mode = TRUE;
00155     last_bitpos_ptr = & last_bitpos[0][0];
00156     for (ci = 0; ci < cinfo->num_components; ci++) 
00157       for (coefi = 0; coefi < DCTSIZE2; coefi++)
00158         *last_bitpos_ptr++ = -1;
00159 #else
00160     ERREXIT(cinfo, JERR_NOT_COMPILED);
00161 #endif
00162   } else {
00163     cinfo->progressive_mode = FALSE;
00164     for (ci = 0; ci < cinfo->num_components; ci++) 
00165       component_sent[ci] = FALSE;
00166   }
00167 
00168   for (scanno = 1; scanno <= cinfo->num_scans; scanptr++, scanno++) {
00169     
00170     ncomps = scanptr->comps_in_scan;
00171     if (ncomps <= 0 || ncomps > MAX_COMPS_IN_SCAN)
00172       ERREXIT2(cinfo, JERR_COMPONENT_COUNT, ncomps, MAX_COMPS_IN_SCAN);
00173     for (ci = 0; ci < ncomps; ci++) {
00174       thisi = scanptr->component_index[ci];
00175       if (thisi < 0 || thisi >= cinfo->num_components)
00176         ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno);
00177       
00178       if (ci > 0 && thisi <= scanptr->component_index[ci-1])
00179         ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno);
00180     }
00181     
00182     Ss = scanptr->Ss;
00183     Se = scanptr->Se;
00184     Ah = scanptr->Ah;
00185     Al = scanptr->Al;
00186     if (cinfo->progressive_mode) {
00187 #ifdef C_PROGRESSIVE_SUPPORTED
00188       
00189 
00190 
00191 
00192 
00193 
00194 
00195 #if BITS_IN_JSAMPLE == 8
00196 #define MAX_AH_AL 10
00197 #else
00198 #define MAX_AH_AL 13
00199 #endif
00200       if (Ss < 0 || Ss >= DCTSIZE2 || Se < Ss || Se >= DCTSIZE2 ||
00201           Ah < 0 || Ah > MAX_AH_AL || Al < 0 || Al > MAX_AH_AL)
00202         ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
00203       if (Ss == 0) {
00204         if (Se != 0)            
00205           ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
00206       } else {
00207         if (ncomps != 1)        
00208           ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
00209       }
00210       for (ci = 0; ci < ncomps; ci++) {
00211         last_bitpos_ptr = & last_bitpos[scanptr->component_index[ci]][0];
00212         if (Ss != 0 && last_bitpos_ptr[0] < 0) 
00213           ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
00214         for (coefi = Ss; coefi <= Se; coefi++) {
00215           if (last_bitpos_ptr[coefi] < 0) {
00216             
00217             if (Ah != 0)
00218               ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
00219           } else {
00220             
00221             if (Ah != last_bitpos_ptr[coefi] || Al != Ah-1)
00222               ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
00223           }
00224           last_bitpos_ptr[coefi] = Al;
00225         }
00226       }
00227 #endif
00228     } else {
00229       
00230       if (Ss != 0 || Se != DCTSIZE2-1 || Ah != 0 || Al != 0)
00231         ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
00232       
00233       for (ci = 0; ci < ncomps; ci++) {
00234         thisi = scanptr->component_index[ci];
00235         if (component_sent[thisi])
00236           ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno);
00237         component_sent[thisi] = TRUE;
00238       }
00239     }
00240   }
00241 
00242   
00243   if (cinfo->progressive_mode) {
00244 #ifdef C_PROGRESSIVE_SUPPORTED
00245     
00246 
00247 
00248 
00249 
00250     for (ci = 0; ci < cinfo->num_components; ci++) {
00251       if (last_bitpos[ci][0] < 0)
00252         ERREXIT(cinfo, JERR_MISSING_DATA);
00253     }
00254 #endif
00255   } else {
00256     for (ci = 0; ci < cinfo->num_components; ci++) {
00257       if (! component_sent[ci])
00258         ERREXIT(cinfo, JERR_MISSING_DATA);
00259     }
00260   }
00261 }
00262 
00263 #endif 
00264 
00265 
00266 LOCAL(void)
00267 select_scan_parameters (j_compress_ptr cinfo)
00268 
00269 {
00270   int ci;
00271 
00272 #ifdef C_MULTISCAN_FILES_SUPPORTED
00273   if (cinfo->scan_info != NULL) {
00274     
00275     my_master_ptr master = (my_master_ptr) cinfo->master;
00276     const jpeg_scan_info * scanptr = cinfo->scan_info + master->scan_number;
00277 
00278     cinfo->comps_in_scan = scanptr->comps_in_scan;
00279     for (ci = 0; ci < scanptr->comps_in_scan; ci++) {
00280       cinfo->cur_comp_info[ci] =
00281         &cinfo->comp_info[scanptr->component_index[ci]];
00282     }
00283     cinfo->Ss = scanptr->Ss;
00284     cinfo->Se = scanptr->Se;
00285     cinfo->Ah = scanptr->Ah;
00286     cinfo->Al = scanptr->Al;
00287   }
00288   else
00289 #endif
00290   {
00291     
00292     if (cinfo->num_components > MAX_COMPS_IN_SCAN)
00293       ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components,
00294                MAX_COMPS_IN_SCAN);
00295     cinfo->comps_in_scan = cinfo->num_components;
00296     for (ci = 0; ci < cinfo->num_components; ci++) {
00297       cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci];
00298     }
00299     cinfo->Ss = 0;
00300     cinfo->Se = DCTSIZE2-1;
00301     cinfo->Ah = 0;
00302     cinfo->Al = 0;
00303   }
00304 }
00305 
00306 
00307 LOCAL(void)
00308 per_scan_setup (j_compress_ptr cinfo)
00309 
00310 
00311 {
00312   int ci, mcublks, tmp;
00313   jpeg_component_info *compptr;
00314   
00315   if (cinfo->comps_in_scan == 1) {
00316     
00317     
00318     compptr = cinfo->cur_comp_info[0];
00319     
00320     
00321     cinfo->MCUs_per_row = compptr->width_in_blocks;
00322     cinfo->MCU_rows_in_scan = compptr->height_in_blocks;
00323     
00324     
00325     compptr->MCU_width = 1;
00326     compptr->MCU_height = 1;
00327     compptr->MCU_blocks = 1;
00328     compptr->MCU_sample_width = DCTSIZE;
00329     compptr->last_col_width = 1;
00330     
00331 
00332 
00333     tmp = (int) (compptr->height_in_blocks % compptr->v_samp_factor);
00334     if (tmp == 0) tmp = compptr->v_samp_factor;
00335     compptr->last_row_height = tmp;
00336     
00337     
00338     cinfo->blocks_in_MCU = 1;
00339     cinfo->MCU_membership[0] = 0;
00340     
00341   } else {
00342     
00343     
00344     if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN)
00345       ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan,
00346                MAX_COMPS_IN_SCAN);
00347     
00348     
00349     cinfo->MCUs_per_row = (JDIMENSION)
00350       jdiv_round_up((long) cinfo->image_width,
00351                     (long) (cinfo->max_h_samp_factor*DCTSIZE));
00352     cinfo->MCU_rows_in_scan = (JDIMENSION)
00353       jdiv_round_up((long) cinfo->image_height,
00354                     (long) (cinfo->max_v_samp_factor*DCTSIZE));
00355     
00356     cinfo->blocks_in_MCU = 0;
00357     
00358     for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
00359       compptr = cinfo->cur_comp_info[ci];
00360       
00361       compptr->MCU_width = compptr->h_samp_factor;
00362       compptr->MCU_height = compptr->v_samp_factor;
00363       compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height;
00364       compptr->MCU_sample_width = compptr->MCU_width * DCTSIZE;
00365       
00366       tmp = (int) (compptr->width_in_blocks % compptr->MCU_width);
00367       if (tmp == 0) tmp = compptr->MCU_width;
00368       compptr->last_col_width = tmp;
00369       tmp = (int) (compptr->height_in_blocks % compptr->MCU_height);
00370       if (tmp == 0) tmp = compptr->MCU_height;
00371       compptr->last_row_height = tmp;
00372       
00373       mcublks = compptr->MCU_blocks;
00374       if (cinfo->blocks_in_MCU + mcublks > C_MAX_BLOCKS_IN_MCU)
00375         ERREXIT(cinfo, JERR_BAD_MCU_SIZE);
00376       while (mcublks-- > 0) {
00377         cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci;
00378       }
00379     }
00380     
00381   }
00382 
00383   
00384   
00385   if (cinfo->restart_in_rows > 0) {
00386     long nominal = (long) cinfo->restart_in_rows * (long) cinfo->MCUs_per_row;
00387     cinfo->restart_interval = (unsigned int) MIN(nominal, 65535L);
00388   }
00389 }
00390 
00391 
00392 
00393 
00394 
00395 
00396 
00397 
00398 
00399 
00400 METHODDEF(void)
00401 prepare_for_pass (j_compress_ptr cinfo)
00402 {
00403   my_master_ptr master = (my_master_ptr) cinfo->master;
00404 
00405   switch (master->pass_type) {
00406   case main_pass:
00407     
00408 
00409 
00410     select_scan_parameters(cinfo);
00411     per_scan_setup(cinfo);
00412     if (! cinfo->raw_data_in) {
00413       (*cinfo->cconvert->start_pass) (cinfo);
00414       (*cinfo->downsample->start_pass) (cinfo);
00415       (*cinfo->prep->start_pass) (cinfo, JBUF_PASS_THRU);
00416     }
00417     (*cinfo->fdct->start_pass) (cinfo);
00418     (*cinfo->entropy->start_pass) (cinfo, cinfo->optimize_coding);
00419     (*cinfo->coef->start_pass) (cinfo,
00420                                 (master->total_passes > 1 ?
00421                                  JBUF_SAVE_AND_PASS : JBUF_PASS_THRU));
00422     (*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU);
00423     if (cinfo->optimize_coding) {
00424       
00425       master->pub.call_pass_startup = FALSE;
00426     } else {
00427       
00428       master->pub.call_pass_startup = TRUE;
00429     }
00430     break;
00431 #ifdef ENTROPY_OPT_SUPPORTED
00432   case huff_opt_pass:
00433     
00434     select_scan_parameters(cinfo);
00435     per_scan_setup(cinfo);
00436     if (cinfo->Ss != 0 || cinfo->Ah == 0 || cinfo->arith_code) {
00437       (*cinfo->entropy->start_pass) (cinfo, TRUE);
00438       (*cinfo->coef->start_pass) (cinfo, JBUF_CRANK_DEST);
00439       master->pub.call_pass_startup = FALSE;
00440       break;
00441     }
00442     
00443 
00444 
00445     master->pass_type = output_pass;
00446     master->pass_number++;
00447     
00448 #endif
00449   case output_pass:
00450     
00451     
00452     if (! cinfo->optimize_coding) {
00453       select_scan_parameters(cinfo);
00454       per_scan_setup(cinfo);
00455     }
00456     (*cinfo->entropy->start_pass) (cinfo, FALSE);
00457     (*cinfo->coef->start_pass) (cinfo, JBUF_CRANK_DEST);
00458     
00459     if (master->scan_number == 0)
00460       (*cinfo->marker->write_frame_header) (cinfo);
00461     (*cinfo->marker->write_scan_header) (cinfo);
00462     master->pub.call_pass_startup = FALSE;
00463     break;
00464   default:
00465     ERREXIT(cinfo, JERR_NOT_COMPILED);
00466   }
00467 
00468   master->pub.is_last_pass = (master->pass_number == master->total_passes-1);
00469 
00470   
00471   if (cinfo->progress != NULL) {
00472     cinfo->progress->completed_passes = master->pass_number;
00473     cinfo->progress->total_passes = master->total_passes;
00474   }
00475 }
00476 
00477 
00478 
00479 
00480 
00481 
00482 
00483 
00484 
00485 
00486 
00487 
00488 METHODDEF(void)
00489 pass_startup (j_compress_ptr cinfo)
00490 {
00491   cinfo->master->call_pass_startup = FALSE; 
00492 
00493   (*cinfo->marker->write_frame_header) (cinfo);
00494   (*cinfo->marker->write_scan_header) (cinfo);
00495 }
00496 
00497 
00498 
00499 
00500 
00501 
00502 METHODDEF(void)
00503 finish_pass_master (j_compress_ptr cinfo)
00504 {
00505   my_master_ptr master = (my_master_ptr) cinfo->master;
00506 
00507   
00508 
00509 
00510   (*cinfo->entropy->finish_pass) (cinfo);
00511 
00512   
00513   switch (master->pass_type) {
00514   case main_pass:
00515     
00516 
00517 
00518     master->pass_type = output_pass;
00519     if (! cinfo->optimize_coding)
00520       master->scan_number++;
00521     break;
00522   case huff_opt_pass:
00523     
00524     master->pass_type = output_pass;
00525     break;
00526   case output_pass:
00527     
00528     if (cinfo->optimize_coding)
00529       master->pass_type = huff_opt_pass;
00530     master->scan_number++;
00531     break;
00532   }
00533 
00534   master->pass_number++;
00535 }
00536 
00537 
00538 
00539 
00540 
00541 
00542 GLOBAL(void)
00543 jinit_c_master_control (j_compress_ptr cinfo, boolean transcode_only)
00544 {
00545   my_master_ptr master;
00546 
00547   master = (my_master_ptr)
00548       (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
00549                                   SIZEOF(my_comp_master));
00550   cinfo->master = (struct jpeg_comp_master *) master;
00551   master->pub.prepare_for_pass = prepare_for_pass;
00552   master->pub.pass_startup = pass_startup;
00553   master->pub.finish_pass = finish_pass_master;
00554   master->pub.is_last_pass = FALSE;
00555 
00556   
00557   initial_setup(cinfo);
00558 
00559   if (cinfo->scan_info != NULL) {
00560 #ifdef C_MULTISCAN_FILES_SUPPORTED
00561     validate_script(cinfo);
00562 #else
00563     ERREXIT(cinfo, JERR_NOT_COMPILED);
00564 #endif
00565   } else {
00566     cinfo->progressive_mode = FALSE;
00567     cinfo->num_scans = 1;
00568   }
00569 
00570   if (cinfo->progressive_mode)  
00571     cinfo->optimize_coding = TRUE; 
00572 
00573   
00574   if (transcode_only) {
00575     
00576     if (cinfo->optimize_coding)
00577       master->pass_type = huff_opt_pass;
00578     else
00579       master->pass_type = output_pass;
00580   } else {
00581     
00582     master->pass_type = main_pass;
00583   }
00584   master->scan_number = 0;
00585   master->pass_number = 0;
00586   if (cinfo->optimize_coding)
00587     master->total_passes = cinfo->num_scans * 2;
00588   else
00589     master->total_passes = cinfo->num_scans;
00590 }