tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

jccoefct.c (17425B)


      1 /*
      2 * jccoefct.c
      3 *
      4 * This file was part of the Independent JPEG Group's software:
      5 * Copyright (C) 1994-1997, Thomas G. Lane.
      6 * libjpeg-turbo Modifications:
      7 * Copyright (C) 2022, D. R. Commander.
      8 * For conditions of distribution and use, see the accompanying README.ijg
      9 * file.
     10 *
     11 * This file contains the coefficient buffer controller for compression.
     12 * This controller is the top level of the lossy JPEG compressor proper.
     13 * The coefficient buffer lies between forward-DCT and entropy encoding steps.
     14 */
     15 
     16 #define JPEG_INTERNALS
     17 #include "jinclude.h"
     18 #include "jpeglib.h"
     19 #include "jsamplecomp.h"
     20 
     21 
     22 /* We use a full-image coefficient buffer when doing Huffman optimization,
     23 * and also for writing multiple-scan JPEG files.  In all cases, the DCT
     24 * step is run during the first pass, and subsequent passes need only read
     25 * the buffered coefficients.
     26 */
     27 #ifdef ENTROPY_OPT_SUPPORTED
     28 #define FULL_COEF_BUFFER_SUPPORTED
     29 #else
     30 #ifdef C_MULTISCAN_FILES_SUPPORTED
     31 #define FULL_COEF_BUFFER_SUPPORTED
     32 #endif
     33 #endif
     34 
     35 
     36 /* Private buffer controller object */
     37 
     38 typedef struct {
     39  struct jpeg_c_coef_controller pub; /* public fields */
     40 
     41  JDIMENSION iMCU_row_num;      /* iMCU row # within image */
     42  JDIMENSION mcu_ctr;           /* counts MCUs processed in current row */
     43  int MCU_vert_offset;          /* counts MCU rows within iMCU row */
     44  int MCU_rows_per_iMCU_row;    /* number of such rows needed */
     45 
     46  /* For single-pass compression, it's sufficient to buffer just one MCU
     47   * (although this may prove a bit slow in practice).  We allocate a
     48   * workspace of C_MAX_BLOCKS_IN_MCU coefficient blocks, and reuse it for each
     49   * MCU constructed and sent.  In multi-pass modes, this array points to the
     50   * current MCU's blocks within the virtual arrays.
     51   */
     52  JBLOCKROW MCU_buffer[C_MAX_BLOCKS_IN_MCU];
     53 
     54  /* In multi-pass modes, we need a virtual block array for each component. */
     55  jvirt_barray_ptr whole_image[MAX_COMPONENTS];
     56 } my_coef_controller;
     57 
     58 typedef my_coef_controller *my_coef_ptr;
     59 
     60 
     61 /* Forward declarations */
     62 METHODDEF(boolean) compress_data(j_compress_ptr cinfo, _JSAMPIMAGE input_buf);
     63 #ifdef FULL_COEF_BUFFER_SUPPORTED
     64 METHODDEF(boolean) compress_first_pass(j_compress_ptr cinfo,
     65                                       _JSAMPIMAGE input_buf);
     66 METHODDEF(boolean) compress_output(j_compress_ptr cinfo,
     67                                   _JSAMPIMAGE input_buf);
     68 #endif
     69 
     70 
     71 LOCAL(void)
     72 start_iMCU_row(j_compress_ptr cinfo)
     73 /* Reset within-iMCU-row counters for a new row */
     74 {
     75  my_coef_ptr coef = (my_coef_ptr)cinfo->coef;
     76 
     77  /* In an interleaved scan, an MCU row is the same as an iMCU row.
     78   * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows.
     79   * But at the bottom of the image, process only what's left.
     80   */
     81  if (cinfo->comps_in_scan > 1) {
     82    coef->MCU_rows_per_iMCU_row = 1;
     83  } else {
     84    if (coef->iMCU_row_num < (cinfo->total_iMCU_rows - 1))
     85      coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor;
     86    else
     87      coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height;
     88  }
     89 
     90  coef->mcu_ctr = 0;
     91  coef->MCU_vert_offset = 0;
     92 }
     93 
     94 
     95 /*
     96 * Initialize for a processing pass.
     97 */
     98 
     99 METHODDEF(void)
    100 start_pass_coef(j_compress_ptr cinfo, J_BUF_MODE pass_mode)
    101 {
    102  my_coef_ptr coef = (my_coef_ptr)cinfo->coef;
    103 
    104  coef->iMCU_row_num = 0;
    105  start_iMCU_row(cinfo);
    106 
    107  switch (pass_mode) {
    108  case JBUF_PASS_THRU:
    109    if (coef->whole_image[0] != NULL)
    110      ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
    111    coef->pub._compress_data = compress_data;
    112    break;
    113 #ifdef FULL_COEF_BUFFER_SUPPORTED
    114  case JBUF_SAVE_AND_PASS:
    115    if (coef->whole_image[0] == NULL)
    116      ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
    117    coef->pub._compress_data = compress_first_pass;
    118    break;
    119  case JBUF_CRANK_DEST:
    120    if (coef->whole_image[0] == NULL)
    121      ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
    122    coef->pub._compress_data = compress_output;
    123    break;
    124 #endif
    125  default:
    126    ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
    127    break;
    128  }
    129 }
    130 
    131 
    132 /*
    133 * Process some data in the single-pass case.
    134 * We process the equivalent of one fully interleaved MCU row ("iMCU" row)
    135 * per call, ie, v_samp_factor block rows for each component in the image.
    136 * Returns TRUE if the iMCU row is completed, FALSE if suspended.
    137 *
    138 * NB: input_buf contains a plane for each component in image,
    139 * which we index according to the component's SOF position.
    140 */
    141 
    142 METHODDEF(boolean)
    143 compress_data(j_compress_ptr cinfo, _JSAMPIMAGE input_buf)
    144 {
    145  my_coef_ptr coef = (my_coef_ptr)cinfo->coef;
    146  JDIMENSION MCU_col_num;       /* index of current MCU within row */
    147  JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1;
    148  JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
    149  int blkn, bi, ci, yindex, yoffset, blockcnt;
    150  JDIMENSION ypos, xpos;
    151  jpeg_component_info *compptr;
    152 
    153  /* Loop to write as much as one whole iMCU row */
    154  for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row;
    155       yoffset++) {
    156    for (MCU_col_num = coef->mcu_ctr; MCU_col_num <= last_MCU_col;
    157         MCU_col_num++) {
    158      /* Determine where data comes from in input_buf and do the DCT thing.
    159       * Each call on forward_DCT processes a horizontal row of DCT blocks
    160       * as wide as an MCU; we rely on having allocated the MCU_buffer[] blocks
    161       * sequentially.  Dummy blocks at the right or bottom edge are filled in
    162       * specially.  The data in them does not matter for image reconstruction,
    163       * so we fill them with values that will encode to the smallest amount of
    164       * data, viz: all zeroes in the AC entries, DC entries equal to previous
    165       * block's DC value.  (Thanks to Thomas Kinsman for this idea.)
    166       */
    167      blkn = 0;
    168      for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
    169        compptr = cinfo->cur_comp_info[ci];
    170        blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width :
    171                                                  compptr->last_col_width;
    172        xpos = MCU_col_num * compptr->MCU_sample_width;
    173        ypos = yoffset * DCTSIZE; /* ypos == (yoffset+yindex) * DCTSIZE */
    174        for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
    175          if (coef->iMCU_row_num < last_iMCU_row ||
    176              yoffset + yindex < compptr->last_row_height) {
    177            (*cinfo->fdct->_forward_DCT) (cinfo, compptr,
    178                                          input_buf[compptr->component_index],
    179                                          coef->MCU_buffer[blkn],
    180                                          ypos, xpos, (JDIMENSION)blockcnt);
    181            if (blockcnt < compptr->MCU_width) {
    182              /* Create some dummy blocks at the right edge of the image. */
    183              jzero_far((void *)coef->MCU_buffer[blkn + blockcnt],
    184                        (compptr->MCU_width - blockcnt) * sizeof(JBLOCK));
    185              for (bi = blockcnt; bi < compptr->MCU_width; bi++) {
    186                coef->MCU_buffer[blkn + bi][0][0] =
    187                  coef->MCU_buffer[blkn + bi - 1][0][0];
    188              }
    189            }
    190          } else {
    191            /* Create a row of dummy blocks at the bottom of the image. */
    192            jzero_far((void *)coef->MCU_buffer[blkn],
    193                      compptr->MCU_width * sizeof(JBLOCK));
    194            for (bi = 0; bi < compptr->MCU_width; bi++) {
    195              coef->MCU_buffer[blkn + bi][0][0] =
    196                coef->MCU_buffer[blkn - 1][0][0];
    197            }
    198          }
    199          blkn += compptr->MCU_width;
    200          ypos += DCTSIZE;
    201        }
    202      }
    203      /* Try to write the MCU.  In event of a suspension failure, we will
    204       * re-DCT the MCU on restart (a bit inefficient, could be fixed...)
    205       */
    206      if (!(*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) {
    207        /* Suspension forced; update state counters and exit */
    208        coef->MCU_vert_offset = yoffset;
    209        coef->mcu_ctr = MCU_col_num;
    210        return FALSE;
    211      }
    212    }
    213    /* Completed an MCU row, but perhaps not an iMCU row */
    214    coef->mcu_ctr = 0;
    215  }
    216  /* Completed the iMCU row, advance counters for next one */
    217  coef->iMCU_row_num++;
    218  start_iMCU_row(cinfo);
    219  return TRUE;
    220 }
    221 
    222 
    223 #ifdef FULL_COEF_BUFFER_SUPPORTED
    224 
    225 /*
    226 * Process some data in the first pass of a multi-pass case.
    227 * We process the equivalent of one fully interleaved MCU row ("iMCU" row)
    228 * per call, ie, v_samp_factor block rows for each component in the image.
    229 * This amount of data is read from the source buffer, DCT'd and quantized,
    230 * and saved into the virtual arrays.  We also generate suitable dummy blocks
    231 * as needed at the right and lower edges.  (The dummy blocks are constructed
    232 * in the virtual arrays, which have been padded appropriately.)  This makes
    233 * it possible for subsequent passes not to worry about real vs. dummy blocks.
    234 *
    235 * We must also emit the data to the entropy encoder.  This is conveniently
    236 * done by calling compress_output() after we've loaded the current strip
    237 * of the virtual arrays.
    238 *
    239 * NB: input_buf contains a plane for each component in image.  All
    240 * components are DCT'd and loaded into the virtual arrays in this pass.
    241 * However, it may be that only a subset of the components are emitted to
    242 * the entropy encoder during this first pass; be careful about looking
    243 * at the scan-dependent variables (MCU dimensions, etc).
    244 */
    245 
    246 METHODDEF(boolean)
    247 compress_first_pass(j_compress_ptr cinfo, _JSAMPIMAGE input_buf)
    248 {
    249  my_coef_ptr coef = (my_coef_ptr)cinfo->coef;
    250  JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
    251  JDIMENSION blocks_across, MCUs_across, MCUindex;
    252  int bi, ci, h_samp_factor, block_row, block_rows, ndummy;
    253  JCOEF lastDC;
    254  jpeg_component_info *compptr;
    255  JBLOCKARRAY buffer;
    256  JBLOCKROW thisblockrow, lastblockrow;
    257 
    258  for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
    259       ci++, compptr++) {
    260    /* Align the virtual buffer for this component. */
    261    buffer = (*cinfo->mem->access_virt_barray)
    262      ((j_common_ptr)cinfo, coef->whole_image[ci],
    263       coef->iMCU_row_num * compptr->v_samp_factor,
    264       (JDIMENSION)compptr->v_samp_factor, TRUE);
    265    /* Count non-dummy DCT block rows in this iMCU row. */
    266    if (coef->iMCU_row_num < last_iMCU_row)
    267      block_rows = compptr->v_samp_factor;
    268    else {
    269      /* NB: can't use last_row_height here, since may not be set! */
    270      block_rows = (int)(compptr->height_in_blocks % compptr->v_samp_factor);
    271      if (block_rows == 0) block_rows = compptr->v_samp_factor;
    272    }
    273    blocks_across = compptr->width_in_blocks;
    274    h_samp_factor = compptr->h_samp_factor;
    275    /* Count number of dummy blocks to be added at the right margin. */
    276    ndummy = (int)(blocks_across % h_samp_factor);
    277    if (ndummy > 0)
    278      ndummy = h_samp_factor - ndummy;
    279    /* Perform DCT for all non-dummy blocks in this iMCU row.  Each call
    280     * on forward_DCT processes a complete horizontal row of DCT blocks.
    281     */
    282    for (block_row = 0; block_row < block_rows; block_row++) {
    283      thisblockrow = buffer[block_row];
    284      (*cinfo->fdct->_forward_DCT) (cinfo, compptr,
    285                                    input_buf[ci], thisblockrow,
    286                                    (JDIMENSION)(block_row * DCTSIZE),
    287                                    (JDIMENSION)0, blocks_across);
    288      if (ndummy > 0) {
    289        /* Create dummy blocks at the right edge of the image. */
    290        thisblockrow += blocks_across; /* => first dummy block */
    291        jzero_far((void *)thisblockrow, ndummy * sizeof(JBLOCK));
    292        lastDC = thisblockrow[-1][0];
    293        for (bi = 0; bi < ndummy; bi++) {
    294          thisblockrow[bi][0] = lastDC;
    295        }
    296      }
    297    }
    298    /* If at end of image, create dummy block rows as needed.
    299     * The tricky part here is that within each MCU, we want the DC values
    300     * of the dummy blocks to match the last real block's DC value.
    301     * This squeezes a few more bytes out of the resulting file...
    302     */
    303    if (coef->iMCU_row_num == last_iMCU_row) {
    304      blocks_across += ndummy;  /* include lower right corner */
    305      MCUs_across = blocks_across / h_samp_factor;
    306      for (block_row = block_rows; block_row < compptr->v_samp_factor;
    307           block_row++) {
    308        thisblockrow = buffer[block_row];
    309        lastblockrow = buffer[block_row - 1];
    310        jzero_far((void *)thisblockrow,
    311                  (size_t)(blocks_across * sizeof(JBLOCK)));
    312        for (MCUindex = 0; MCUindex < MCUs_across; MCUindex++) {
    313          lastDC = lastblockrow[h_samp_factor - 1][0];
    314          for (bi = 0; bi < h_samp_factor; bi++) {
    315            thisblockrow[bi][0] = lastDC;
    316          }
    317          thisblockrow += h_samp_factor; /* advance to next MCU in row */
    318          lastblockrow += h_samp_factor;
    319        }
    320      }
    321    }
    322  }
    323  /* NB: compress_output will increment iMCU_row_num if successful.
    324   * A suspension return will result in redoing all the work above next time.
    325   */
    326 
    327  /* Emit data to the entropy encoder, sharing code with subsequent passes */
    328  return compress_output(cinfo, input_buf);
    329 }
    330 
    331 
    332 /*
    333 * Process some data in subsequent passes of a multi-pass case.
    334 * We process the equivalent of one fully interleaved MCU row ("iMCU" row)
    335 * per call, ie, v_samp_factor block rows for each component in the scan.
    336 * The data is obtained from the virtual arrays and fed to the entropy coder.
    337 * Returns TRUE if the iMCU row is completed, FALSE if suspended.
    338 *
    339 * NB: input_buf is ignored; it is likely to be a NULL pointer.
    340 */
    341 
    342 METHODDEF(boolean)
    343 compress_output(j_compress_ptr cinfo, _JSAMPIMAGE input_buf)
    344 {
    345  my_coef_ptr coef = (my_coef_ptr)cinfo->coef;
    346  JDIMENSION MCU_col_num;       /* index of current MCU within row */
    347  int blkn, ci, xindex, yindex, yoffset;
    348  JDIMENSION start_col;
    349  JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN];
    350  JBLOCKROW buffer_ptr;
    351  jpeg_component_info *compptr;
    352 
    353  /* Align the virtual buffers for the components used in this scan.
    354   * NB: during first pass, this is safe only because the buffers will
    355   * already be aligned properly, so jmemmgr.c won't need to do any I/O.
    356   */
    357  for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
    358    compptr = cinfo->cur_comp_info[ci];
    359    buffer[ci] = (*cinfo->mem->access_virt_barray)
    360      ((j_common_ptr)cinfo, coef->whole_image[compptr->component_index],
    361       coef->iMCU_row_num * compptr->v_samp_factor,
    362       (JDIMENSION)compptr->v_samp_factor, FALSE);
    363  }
    364 
    365  /* Loop to process one whole iMCU row */
    366  for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row;
    367       yoffset++) {
    368    for (MCU_col_num = coef->mcu_ctr; MCU_col_num < cinfo->MCUs_per_row;
    369         MCU_col_num++) {
    370      /* Construct list of pointers to DCT blocks belonging to this MCU */
    371      blkn = 0;                 /* index of current DCT block within MCU */
    372      for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
    373        compptr = cinfo->cur_comp_info[ci];
    374        start_col = MCU_col_num * compptr->MCU_width;
    375        for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
    376          buffer_ptr = buffer[ci][yindex + yoffset] + start_col;
    377          for (xindex = 0; xindex < compptr->MCU_width; xindex++) {
    378            coef->MCU_buffer[blkn++] = buffer_ptr++;
    379          }
    380        }
    381      }
    382      /* Try to write the MCU. */
    383      if (!(*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) {
    384        /* Suspension forced; update state counters and exit */
    385        coef->MCU_vert_offset = yoffset;
    386        coef->mcu_ctr = MCU_col_num;
    387        return FALSE;
    388      }
    389    }
    390    /* Completed an MCU row, but perhaps not an iMCU row */
    391    coef->mcu_ctr = 0;
    392  }
    393  /* Completed the iMCU row, advance counters for next one */
    394  coef->iMCU_row_num++;
    395  start_iMCU_row(cinfo);
    396  return TRUE;
    397 }
    398 
    399 #endif /* FULL_COEF_BUFFER_SUPPORTED */
    400 
    401 
    402 /*
    403 * Initialize coefficient buffer controller.
    404 */
    405 
    406 GLOBAL(void)
    407 _jinit_c_coef_controller(j_compress_ptr cinfo, boolean need_full_buffer)
    408 {
    409  my_coef_ptr coef;
    410 
    411  if (cinfo->data_precision != BITS_IN_JSAMPLE)
    412    ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
    413 
    414  coef = (my_coef_ptr)
    415    (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
    416                                sizeof(my_coef_controller));
    417  cinfo->coef = (struct jpeg_c_coef_controller *)coef;
    418  coef->pub.start_pass = start_pass_coef;
    419 
    420  /* Create the coefficient buffer. */
    421  if (need_full_buffer) {
    422 #ifdef FULL_COEF_BUFFER_SUPPORTED
    423    /* Allocate a full-image virtual array for each component, */
    424    /* padded to a multiple of samp_factor DCT blocks in each direction. */
    425    int ci;
    426    jpeg_component_info *compptr;
    427 
    428    for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
    429         ci++, compptr++) {
    430      coef->whole_image[ci] = (*cinfo->mem->request_virt_barray)
    431        ((j_common_ptr)cinfo, JPOOL_IMAGE, FALSE,
    432         (JDIMENSION)jround_up((long)compptr->width_in_blocks,
    433                               (long)compptr->h_samp_factor),
    434         (JDIMENSION)jround_up((long)compptr->height_in_blocks,
    435                               (long)compptr->v_samp_factor),
    436         (JDIMENSION)compptr->v_samp_factor);
    437    }
    438 #else
    439    ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
    440 #endif
    441  } else {
    442    /* We only need a single-MCU buffer. */
    443    JBLOCKROW buffer;
    444    int i;
    445 
    446    buffer = (JBLOCKROW)
    447      (*cinfo->mem->alloc_large) ((j_common_ptr)cinfo, JPOOL_IMAGE,
    448                                  C_MAX_BLOCKS_IN_MCU * sizeof(JBLOCK));
    449    for (i = 0; i < C_MAX_BLOCKS_IN_MCU; i++) {
    450      coef->MCU_buffer[i] = buffer + i;
    451    }
    452    coef->whole_image[0] = NULL; /* flag for no virtual arrays */
    453  }
    454 }