LCOV - code coverage report
Current view: directory - media/libjpeg - jcprepct.c (source / functions) Found Hit Coverage
Test: app.info Lines: 118 45 38.1 %
Date: 2012-06-02 Functions: 6 3 50.0 %

       1                 : /*
       2                 :  * jcprepct.c
       3                 :  *
       4                 :  * Copyright (C) 1994-1996, Thomas G. Lane.
       5                 :  * This file is part of the Independent JPEG Group's software.
       6                 :  * For conditions of distribution and use, see the accompanying README file.
       7                 :  *
       8                 :  * This file contains the compression preprocessing controller.
       9                 :  * This controller manages the color conversion, downsampling,
      10                 :  * and edge expansion steps.
      11                 :  *
      12                 :  * Most of the complexity here is associated with buffering input rows
      13                 :  * as required by the downsampler.  See the comments at the head of
      14                 :  * jcsample.c for the downsampler's needs.
      15                 :  */
      16                 : 
      17                 : #define JPEG_INTERNALS
      18                 : #include "jinclude.h"
      19                 : #include "jpeglib.h"
      20                 : 
      21                 : 
      22                 : /* At present, jcsample.c can request context rows only for smoothing.
      23                 :  * In the future, we might also need context rows for CCIR601 sampling
      24                 :  * or other more-complex downsampling procedures.  The code to support
      25                 :  * context rows should be compiled only if needed.
      26                 :  */
      27                 : #ifdef INPUT_SMOOTHING_SUPPORTED
      28                 : #define CONTEXT_ROWS_SUPPORTED
      29                 : #endif
      30                 : 
      31                 : 
      32                 : /*
      33                 :  * For the simple (no-context-row) case, we just need to buffer one
      34                 :  * row group's worth of pixels for the downsampling step.  At the bottom of
      35                 :  * the image, we pad to a full row group by replicating the last pixel row.
      36                 :  * The downsampler's last output row is then replicated if needed to pad
      37                 :  * out to a full iMCU row.
      38                 :  *
      39                 :  * When providing context rows, we must buffer three row groups' worth of
      40                 :  * pixels.  Three row groups are physically allocated, but the row pointer
      41                 :  * arrays are made five row groups high, with the extra pointers above and
      42                 :  * below "wrapping around" to point to the last and first real row groups.
      43                 :  * This allows the downsampler to access the proper context rows.
      44                 :  * At the top and bottom of the image, we create dummy context rows by
      45                 :  * copying the first or last real pixel row.  This copying could be avoided
      46                 :  * by pointer hacking as is done in jdmainct.c, but it doesn't seem worth the
      47                 :  * trouble on the compression side.
      48                 :  */
      49                 : 
      50                 : 
      51                 : /* Private buffer controller object */
      52                 : 
      53                 : typedef struct {
      54                 :   struct jpeg_c_prep_controller pub; /* public fields */
      55                 : 
      56                 :   /* Downsampling input buffer.  This buffer holds color-converted data
      57                 :    * until we have enough to do a downsample step.
      58                 :    */
      59                 :   JSAMPARRAY color_buf[MAX_COMPONENTS];
      60                 : 
      61                 :   JDIMENSION rows_to_go;        /* counts rows remaining in source image */
      62                 :   int next_buf_row;             /* index of next row to store in color_buf */
      63                 : 
      64                 : #ifdef CONTEXT_ROWS_SUPPORTED   /* only needed for context case */
      65                 :   int this_row_group;           /* starting row index of group to process */
      66                 :   int next_buf_stop;            /* downsample when we reach this index */
      67                 : #endif
      68                 : } my_prep_controller;
      69                 : 
      70                 : typedef my_prep_controller * my_prep_ptr;
      71                 : 
      72                 : 
      73                 : /*
      74                 :  * Initialize for a processing pass.
      75                 :  */
      76                 : 
      77                 : METHODDEF(void)
      78               3 : start_pass_prep (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
      79                 : {
      80               3 :   my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
      81                 : 
      82               3 :   if (pass_mode != JBUF_PASS_THRU)
      83               0 :     ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
      84                 : 
      85                 :   /* Initialize total-height counter for detecting bottom of image */
      86               3 :   prep->rows_to_go = cinfo->image_height;
      87                 :   /* Mark the conversion buffer empty */
      88               3 :   prep->next_buf_row = 0;
      89                 : #ifdef CONTEXT_ROWS_SUPPORTED
      90                 :   /* Preset additional state variables for context mode.
      91                 :    * These aren't used in non-context mode, so we needn't test which mode.
      92                 :    */
      93               3 :   prep->this_row_group = 0;
      94                 :   /* Set next_buf_stop to stop after two row groups have been read in. */
      95               3 :   prep->next_buf_stop = 2 * cinfo->max_v_samp_factor;
      96                 : #endif
      97               3 : }
      98                 : 
      99                 : 
     100                 : /*
     101                 :  * Expand an image vertically from height input_rows to height output_rows,
     102                 :  * by duplicating the bottom row.
     103                 :  */
     104                 : 
     105                 : LOCAL(void)
     106               0 : expand_bottom_edge (JSAMPARRAY image_data, JDIMENSION num_cols,
     107                 :                     int input_rows, int output_rows)
     108                 : {
     109                 :   register int row;
     110                 : 
     111               0 :   for (row = input_rows; row < output_rows; row++) {
     112               0 :     jcopy_sample_rows(image_data, input_rows-1, image_data, row,
     113                 :                       1, num_cols);
     114                 :   }
     115               0 : }
     116                 : 
     117                 : 
     118                 : /*
     119                 :  * Process some data in the simple no-context case.
     120                 :  *
     121                 :  * Preprocessor output data is counted in "row groups".  A row group
     122                 :  * is defined to be v_samp_factor sample rows of each component.
     123                 :  * Downsampling will produce this much data from each max_v_samp_factor
     124                 :  * input rows.
     125                 :  */
     126                 : 
     127                 : METHODDEF(void)
     128             159 : pre_process_data (j_compress_ptr cinfo,
     129                 :                   JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
     130                 :                   JDIMENSION in_rows_avail,
     131                 :                   JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr,
     132                 :                   JDIMENSION out_row_groups_avail)
     133                 : {
     134             159 :   my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
     135                 :   int numrows, ci;
     136                 :   JDIMENSION inrows;
     137                 :   jpeg_component_info * compptr;
     138                 : 
     139             606 :   while (*in_row_ctr < in_rows_avail &&
     140             144 :          *out_row_group_ctr < out_row_groups_avail) {
     141                 :     /* Do color conversion to fill the conversion buffer. */
     142             144 :     inrows = in_rows_avail - *in_row_ctr;
     143             144 :     numrows = cinfo->max_v_samp_factor - prep->next_buf_row;
     144             144 :     numrows = (int) MIN((JDIMENSION) numrows, inrows);
     145             288 :     (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr,
     146                 :                                        prep->color_buf,
     147             144 :                                        (JDIMENSION) prep->next_buf_row,
     148                 :                                        numrows);
     149             144 :     *in_row_ctr += numrows;
     150             144 :     prep->next_buf_row += numrows;
     151             144 :     prep->rows_to_go -= numrows;
     152                 :     /* If at bottom of image, pad to fill the conversion buffer. */
     153             147 :     if (prep->rows_to_go == 0 &&
     154               3 :         prep->next_buf_row < cinfo->max_v_samp_factor) {
     155               0 :       for (ci = 0; ci < cinfo->num_components; ci++) {
     156               0 :         expand_bottom_edge(prep->color_buf[ci], cinfo->image_width,
     157                 :                            prep->next_buf_row, cinfo->max_v_samp_factor);
     158                 :       }
     159               0 :       prep->next_buf_row = cinfo->max_v_samp_factor;
     160                 :     }
     161                 :     /* If we've filled the conversion buffer, empty it. */
     162             144 :     if (prep->next_buf_row == cinfo->max_v_samp_factor) {
     163             144 :       (*cinfo->downsample->downsample) (cinfo,
     164                 :                                         prep->color_buf, (JDIMENSION) 0,
     165                 :                                         output_buf, *out_row_group_ctr);
     166             144 :       prep->next_buf_row = 0;
     167             144 :       (*out_row_group_ctr)++;
     168                 :     }
     169                 :     /* If at bottom of image, pad the output to a full iMCU height.
     170                 :      * Note we assume the caller is providing a one-iMCU-height output buffer!
     171                 :      */
     172             147 :     if (prep->rows_to_go == 0 &&
     173               3 :         *out_row_group_ctr < out_row_groups_avail) {
     174               0 :       for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
     175               0 :            ci++, compptr++) {
     176               0 :         expand_bottom_edge(output_buf[ci],
     177               0 :                            compptr->width_in_blocks * DCTSIZE,
     178               0 :                            (int) (*out_row_group_ctr * compptr->v_samp_factor),
     179               0 :                            (int) (out_row_groups_avail * compptr->v_samp_factor));
     180                 :       }
     181               0 :       *out_row_group_ctr = out_row_groups_avail;
     182               0 :       break;                    /* can exit outer loop without test */
     183                 :     }
     184                 :   }
     185             159 : }
     186                 : 
     187                 : 
     188                 : #ifdef CONTEXT_ROWS_SUPPORTED
     189                 : 
     190                 : /*
     191                 :  * Process some data in the context case.
     192                 :  */
     193                 : 
     194                 : METHODDEF(void)
     195               0 : pre_process_context (j_compress_ptr cinfo,
     196                 :                      JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
     197                 :                      JDIMENSION in_rows_avail,
     198                 :                      JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr,
     199                 :                      JDIMENSION out_row_groups_avail)
     200                 : {
     201               0 :   my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
     202                 :   int numrows, ci;
     203               0 :   int buf_height = cinfo->max_v_samp_factor * 3;
     204                 :   JDIMENSION inrows;
     205                 : 
     206               0 :   while (*out_row_group_ctr < out_row_groups_avail) {
     207               0 :     if (*in_row_ctr < in_rows_avail) {
     208                 :       /* Do color conversion to fill the conversion buffer. */
     209               0 :       inrows = in_rows_avail - *in_row_ctr;
     210               0 :       numrows = prep->next_buf_stop - prep->next_buf_row;
     211               0 :       numrows = (int) MIN((JDIMENSION) numrows, inrows);
     212               0 :       (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr,
     213                 :                                          prep->color_buf,
     214               0 :                                          (JDIMENSION) prep->next_buf_row,
     215                 :                                          numrows);
     216                 :       /* Pad at top of image, if first time through */
     217               0 :       if (prep->rows_to_go == cinfo->image_height) {
     218               0 :         for (ci = 0; ci < cinfo->num_components; ci++) {
     219                 :           int row;
     220               0 :           for (row = 1; row <= cinfo->max_v_samp_factor; row++) {
     221               0 :             jcopy_sample_rows(prep->color_buf[ci], 0,
     222                 :                               prep->color_buf[ci], -row,
     223                 :                               1, cinfo->image_width);
     224                 :           }
     225                 :         }
     226                 :       }
     227               0 :       *in_row_ctr += numrows;
     228               0 :       prep->next_buf_row += numrows;
     229               0 :       prep->rows_to_go -= numrows;
     230                 :     } else {
     231                 :       /* Return for more data, unless we are at the bottom of the image. */
     232               0 :       if (prep->rows_to_go != 0)
     233               0 :         break;
     234                 :       /* When at bottom of image, pad to fill the conversion buffer. */
     235               0 :       if (prep->next_buf_row < prep->next_buf_stop) {
     236               0 :         for (ci = 0; ci < cinfo->num_components; ci++) {
     237               0 :           expand_bottom_edge(prep->color_buf[ci], cinfo->image_width,
     238                 :                              prep->next_buf_row, prep->next_buf_stop);
     239                 :         }
     240               0 :         prep->next_buf_row = prep->next_buf_stop;
     241                 :       }
     242                 :     }
     243                 :     /* If we've gotten enough data, downsample a row group. */
     244               0 :     if (prep->next_buf_row == prep->next_buf_stop) {
     245               0 :       (*cinfo->downsample->downsample) (cinfo,
     246                 :                                         prep->color_buf,
     247               0 :                                         (JDIMENSION) prep->this_row_group,
     248                 :                                         output_buf, *out_row_group_ctr);
     249               0 :       (*out_row_group_ctr)++;
     250                 :       /* Advance pointers with wraparound as necessary. */
     251               0 :       prep->this_row_group += cinfo->max_v_samp_factor;
     252               0 :       if (prep->this_row_group >= buf_height)
     253               0 :         prep->this_row_group = 0;
     254               0 :       if (prep->next_buf_row >= buf_height)
     255               0 :         prep->next_buf_row = 0;
     256               0 :       prep->next_buf_stop = prep->next_buf_row + cinfo->max_v_samp_factor;
     257                 :     }
     258                 :   }
     259               0 : }
     260                 : 
     261                 : 
     262                 : /*
     263                 :  * Create the wrapped-around downsampling input buffer needed for context mode.
     264                 :  */
     265                 : 
     266                 : LOCAL(void)
     267               0 : create_context_buffer (j_compress_ptr cinfo)
     268                 : {
     269               0 :   my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
     270               0 :   int rgroup_height = cinfo->max_v_samp_factor;
     271                 :   int ci, i;
     272                 :   jpeg_component_info * compptr;
     273                 :   JSAMPARRAY true_buffer, fake_buffer;
     274                 : 
     275                 :   /* Grab enough space for fake row pointers for all the components;
     276                 :    * we need five row groups' worth of pointers for each component.
     277                 :    */
     278               0 :   fake_buffer = (JSAMPARRAY)
     279               0 :     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
     280               0 :                                 (cinfo->num_components * 5 * rgroup_height) *
     281                 :                                 SIZEOF(JSAMPROW));
     282                 : 
     283               0 :   for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
     284               0 :        ci++, compptr++) {
     285                 :     /* Allocate the actual buffer space (3 row groups) for this component.
     286                 :      * We make the buffer wide enough to allow the downsampler to edge-expand
     287                 :      * horizontally within the buffer, if it so chooses.
     288                 :      */
     289               0 :     true_buffer = (*cinfo->mem->alloc_sarray)
     290               0 :       ((j_common_ptr) cinfo, JPOOL_IMAGE,
     291               0 :        (JDIMENSION) (((long) compptr->width_in_blocks * DCTSIZE *
     292               0 :                       cinfo->max_h_samp_factor) / compptr->h_samp_factor),
     293               0 :        (JDIMENSION) (3 * rgroup_height));
     294                 :     /* Copy true buffer row pointers into the middle of the fake row array */
     295               0 :     MEMCOPY(fake_buffer + rgroup_height, true_buffer,
     296                 :             3 * rgroup_height * SIZEOF(JSAMPROW));
     297                 :     /* Fill in the above and below wraparound pointers */
     298               0 :     for (i = 0; i < rgroup_height; i++) {
     299               0 :       fake_buffer[i] = true_buffer[2 * rgroup_height + i];
     300               0 :       fake_buffer[4 * rgroup_height + i] = true_buffer[i];
     301                 :     }
     302               0 :     prep->color_buf[ci] = fake_buffer + rgroup_height;
     303               0 :     fake_buffer += 5 * rgroup_height; /* point to space for next component */
     304                 :   }
     305               0 : }
     306                 : 
     307                 : #endif /* CONTEXT_ROWS_SUPPORTED */
     308                 : 
     309                 : 
     310                 : /*
     311                 :  * Initialize preprocessing controller.
     312                 :  */
     313                 : 
     314                 : GLOBAL(void)
     315               3 : jinit_c_prep_controller (j_compress_ptr cinfo, boolean need_full_buffer)
     316                 : {
     317                 :   my_prep_ptr prep;
     318                 :   int ci;
     319                 :   jpeg_component_info * compptr;
     320                 : 
     321               3 :   if (need_full_buffer)         /* safety check */
     322               0 :     ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
     323                 : 
     324               3 :   prep = (my_prep_ptr)
     325               3 :     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
     326                 :                                 SIZEOF(my_prep_controller));
     327               3 :   cinfo->prep = (struct jpeg_c_prep_controller *) prep;
     328               3 :   prep->pub.start_pass = start_pass_prep;
     329                 : 
     330                 :   /* Allocate the color conversion buffer.
     331                 :    * We make the buffer wide enough to allow the downsampler to edge-expand
     332                 :    * horizontally within the buffer, if it so chooses.
     333                 :    */
     334               3 :   if (cinfo->downsample->need_context_rows) {
     335                 :     /* Set up to provide context rows */
     336                 : #ifdef CONTEXT_ROWS_SUPPORTED
     337               0 :     prep->pub.pre_process_data = pre_process_context;
     338               0 :     create_context_buffer(cinfo);
     339                 : #else
     340                 :     ERREXIT(cinfo, JERR_NOT_COMPILED);
     341                 : #endif
     342                 :   } else {
     343                 :     /* No context, just make it tall enough for one row group */
     344               3 :     prep->pub.pre_process_data = pre_process_data;
     345              15 :     for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
     346               9 :          ci++, compptr++) {
     347              18 :       prep->color_buf[ci] = (*cinfo->mem->alloc_sarray)
     348              27 :         ((j_common_ptr) cinfo, JPOOL_IMAGE,
     349              18 :          (JDIMENSION) (((long) compptr->width_in_blocks * DCTSIZE *
     350              18 :                         cinfo->max_h_samp_factor) / compptr->h_samp_factor),
     351               9 :          (JDIMENSION) cinfo->max_v_samp_factor);
     352                 :     }
     353                 :   }
     354               3 : }

Generated by: LCOV version 1.7