LCOV - code coverage report
Current view: top level - media/libjpeg - jcprepct.c (source / functions) Hit Total Coverage
Test: output.info Lines: 0 120 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 6 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13