Coverage Report

Created: 2022-11-14 06:33

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