Home | History | Annotate | Download | only in libjpeg-turbo
      1 /*
      2  * jcmainct.c
      3  *
      4  * This file was 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 file.
      9  *
     10  * This file contains the main buffer controller for compression.
     11  * The main buffer lies between the pre-processor and the JPEG
     12  * compressor proper; it holds downsampled data in the JPEG colorspace.
     13  */
     14 
     15 #define JPEG_INTERNALS
     16 #include "jinclude.h"
     17 #include "jpeglib.h"
     18 
     19 
     20 /* Private buffer controller object */
     21 
     22 typedef struct {
     23   struct jpeg_c_main_controller pub; /* public fields */
     24 
     25   JDIMENSION cur_iMCU_row;      /* number of current iMCU row */
     26   JDIMENSION rowgroup_ctr;      /* counts row groups received in iMCU row */
     27   boolean suspended;            /* remember if we suspended output */
     28   J_BUF_MODE pass_mode;         /* current operating mode */
     29 
     30   /* If using just a strip buffer, this points to the entire set of buffers
     31    * (we allocate one for each component).  In the full-image case, this
     32    * points to the currently accessible strips of the virtual arrays.
     33    */
     34   JSAMPARRAY buffer[MAX_COMPONENTS];
     35 } my_main_controller;
     36 
     37 typedef my_main_controller * my_main_ptr;
     38 
     39 
     40 /* Forward declarations */
     41 METHODDEF(void) process_data_simple_main
     42         (j_compress_ptr cinfo, JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
     43          JDIMENSION in_rows_avail);
     44 
     45 
     46 /*
     47  * Initialize for a processing pass.
     48  */
     49 
     50 METHODDEF(void)
     51 start_pass_main (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
     52 {
     53   my_main_ptr main_ptr = (my_main_ptr) cinfo->main;
     54 
     55   /* Do nothing in raw-data mode. */
     56   if (cinfo->raw_data_in)
     57     return;
     58 
     59   if (pass_mode != JBUF_PASS_THRU)
     60     ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
     61 
     62   main_ptr->cur_iMCU_row = 0;   /* initialize counters */
     63   main_ptr->rowgroup_ctr = 0;
     64   main_ptr->suspended = FALSE;
     65   main_ptr->pass_mode = pass_mode;      /* save mode for use by process_data */
     66   main_ptr->pub.process_data = process_data_simple_main;
     67 }
     68 
     69 
     70 /*
     71  * Process some data.
     72  * This routine handles the simple pass-through mode,
     73  * where we have only a strip buffer.
     74  */
     75 
     76 METHODDEF(void)
     77 process_data_simple_main (j_compress_ptr cinfo,
     78                           JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
     79                           JDIMENSION in_rows_avail)
     80 {
     81   my_main_ptr main_ptr = (my_main_ptr) cinfo->main;
     82 
     83   while (main_ptr->cur_iMCU_row < cinfo->total_iMCU_rows) {
     84     /* Read input data if we haven't filled the main buffer yet */
     85     if (main_ptr->rowgroup_ctr < DCTSIZE)
     86       (*cinfo->prep->pre_process_data) (cinfo,
     87                                         input_buf, in_row_ctr, in_rows_avail,
     88                                         main_ptr->buffer, &main_ptr->rowgroup_ctr,
     89                                         (JDIMENSION) DCTSIZE);
     90 
     91     /* If we don't have a full iMCU row buffered, return to application for
     92      * more data.  Note that preprocessor will always pad to fill the iMCU row
     93      * at the bottom of the image.
     94      */
     95     if (main_ptr->rowgroup_ctr != DCTSIZE)
     96       return;
     97 
     98     /* Send the completed row to the compressor */
     99     if (! (*cinfo->coef->compress_data) (cinfo, main_ptr->buffer)) {
    100       /* If compressor did not consume the whole row, then we must need to
    101        * suspend processing and return to the application.  In this situation
    102        * we pretend we didn't yet consume the last input row; otherwise, if
    103        * it happened to be the last row of the image, the application would
    104        * think we were done.
    105        */
    106       if (! main_ptr->suspended) {
    107         (*in_row_ctr)--;
    108         main_ptr->suspended = TRUE;
    109       }
    110       return;
    111     }
    112     /* We did finish the row.  Undo our little suspension hack if a previous
    113      * call suspended; then mark the main buffer empty.
    114      */
    115     if (main_ptr->suspended) {
    116       (*in_row_ctr)++;
    117       main_ptr->suspended = FALSE;
    118     }
    119     main_ptr->rowgroup_ctr = 0;
    120     main_ptr->cur_iMCU_row++;
    121   }
    122 }
    123 
    124 
    125 /*
    126  * Initialize main buffer controller.
    127  */
    128 
    129 GLOBAL(void)
    130 jinit_c_main_controller (j_compress_ptr cinfo, boolean need_full_buffer)
    131 {
    132   my_main_ptr main_ptr;
    133   int ci;
    134   jpeg_component_info *compptr;
    135 
    136   main_ptr = (my_main_ptr)
    137     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
    138                                 sizeof(my_main_controller));
    139   cinfo->main = (struct jpeg_c_main_controller *) main_ptr;
    140   main_ptr->pub.start_pass = start_pass_main;
    141 
    142   /* We don't need to create a buffer in raw-data mode. */
    143   if (cinfo->raw_data_in)
    144     return;
    145 
    146   /* Create the buffer.  It holds downsampled data, so each component
    147    * may be of a different size.
    148    */
    149   if (need_full_buffer) {
    150     ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
    151   } else {
    152     /* Allocate a strip buffer for each component */
    153     for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
    154          ci++, compptr++) {
    155       main_ptr->buffer[ci] = (*cinfo->mem->alloc_sarray)
    156         ((j_common_ptr) cinfo, JPOOL_IMAGE,
    157          compptr->width_in_blocks * DCTSIZE,
    158          (JDIMENSION) (compptr->v_samp_factor * DCTSIZE));
    159     }
    160   }
    161 }
    162