Coverage Report

Created: 2026-08-14 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/dcmtk/dcmjpeg/libijg8/jddiffct.c
Line
Count
Source
1
/*
2
 * jddiffct.c
3
 *
4
 * Copyright (C) 1994-1998, 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 [un]difference buffer controller for decompression.
9
 * This controller is the top level of the lossless JPEG decompressor proper.
10
 * The difference buffer lies between the entropy decoding and
11
 * prediction/undifferencing steps.  The undifference buffer lies between the
12
 * prediction/undifferencing and scaling steps.
13
 *
14
 * In buffered-image mode, this controller is the interface between
15
 * input-oriented processing and output-oriented processing.
16
 */
17
18
#define JPEG_INTERNALS
19
#include "jinclude8.h"
20
#include "jpeglib8.h"
21
#include "jlossls8.h"
22
23
24
#ifdef D_LOSSLESS_SUPPORTED
25
26
/* Private buffer controller object */
27
28
typedef struct {
29
  /* These variables keep track of the current location of the input side. */
30
  /* cinfo->input_iMCU_row is also used for this. */
31
  JDIMENSION MCU_ctr;       /* counts MCUs processed in current row */
32
  unsigned int restart_rows_to_go;  /* MCU-rows left in this restart interval */
33
  unsigned int MCU_vert_offset;     /* counts MCU rows within iMCU row */
34
  unsigned int MCU_rows_per_iMCU_row;   /* number of such rows needed */
35
36
  /* The output side's location is represented by cinfo->output_iMCU_row. */
37
38
  JDIFFARRAY diff_buf[MAX_COMPONENTS];  /* iMCU row of differences */
39
  JDIFFARRAY undiff_buf[MAX_COMPONENTS]; /* iMCU row of undiff'd samples */
40
41
#ifdef D_MULTISCAN_FILES_SUPPORTED
42
  /* In multi-pass modes, we need a virtual sample array for each component. */
43
  jvirt_sarray_ptr whole_image[MAX_COMPONENTS];
44
#endif
45
} d_diff_controller;
46
47
typedef d_diff_controller * d_diff_ptr;
48
49
/* Forward declarations */
50
METHODDEF(int) decompress_data
51
    JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf));
52
#ifdef D_MULTISCAN_FILES_SUPPORTED
53
METHODDEF(int) output_data
54
    JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf));
55
#endif
56
57
58
LOCAL(void)
59
start_iMCU_row (j_decompress_ptr cinfo)
60
/* Reset within-iMCU-row counters for a new row (input side) */
61
0
{
62
0
  j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
63
0
  d_diff_ptr diff = (d_diff_ptr) losslsd->diff_private;
64
65
  /* In an interleaved scan, an MCU row is the same as an iMCU row.
66
   * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows.
67
   * But at the bottom of the image, process only what's left.
68
   */
69
0
  if (cinfo->comps_in_scan > 1) {
70
0
    diff->MCU_rows_per_iMCU_row = 1;
71
0
  } else {
72
0
    if (cinfo->input_iMCU_row < (cinfo->total_iMCU_rows-1))
73
0
      diff->MCU_rows_per_iMCU_row = (JDIMENSION)cinfo->cur_comp_info[0]->v_samp_factor;
74
0
    else
75
0
      diff->MCU_rows_per_iMCU_row = (JDIMENSION)cinfo->cur_comp_info[0]->last_row_height;
76
0
  }
77
78
0
  diff->MCU_ctr = 0;
79
0
  diff->MCU_vert_offset = 0;
80
0
}
81
82
83
/*
84
 * Initialize for an input processing pass.
85
 */
86
87
METHODDEF(void)
88
start_input_pass (j_decompress_ptr cinfo)
89
0
{
90
0
  j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
91
0
  d_diff_ptr diff = (d_diff_ptr) losslsd->diff_private;
92
93
  /* Check that the restart interval is an integer multiple of the number 
94
   * of MCU in an MCU-row.
95
   */
96
0
  if (cinfo->restart_interval % cinfo->MCUs_per_row != 0)
97
0
    ERREXIT2(cinfo, JERR_BAD_RESTART,
98
0
         (int)cinfo->restart_interval, (int)cinfo->MCUs_per_row);
99
100
  /* Initialize restart counter */
101
0
  diff->restart_rows_to_go = cinfo->restart_interval / cinfo->MCUs_per_row;
102
103
0
  cinfo->input_iMCU_row = 0;
104
0
  start_iMCU_row(cinfo);
105
0
}
106
107
108
/*
109
 * Check for a restart marker & resynchronize decoder, undifferencer.
110
 * Returns FALSE if must suspend.
111
 */
112
113
METHODDEF(boolean)
114
process_restart (j_decompress_ptr cinfo)
115
0
{
116
0
  j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
117
0
  d_diff_ptr diff = (d_diff_ptr) losslsd->diff_private;
118
119
0
  if (! (*losslsd->entropy_process_restart) (cinfo))
120
0
    return FALSE;
121
122
0
  (*losslsd->predict_process_restart) (cinfo);
123
124
  /* Reset restart counter */
125
0
  diff->restart_rows_to_go = cinfo->restart_interval / cinfo->MCUs_per_row;
126
127
0
  return TRUE;
128
0
}
129
130
131
/*
132
 * Initialize for an output processing pass.
133
 */
134
135
METHODDEF(void)
136
start_output_pass (j_decompress_ptr cinfo)
137
0
{
138
0
  cinfo->output_iMCU_row = 0;
139
0
}
140
141
142
/*
143
 * Decompress and return some data in the supplied buffer.
144
 * Always attempts to emit one fully interleaved MCU row ("iMCU" row).
145
 * Input and output must run in lockstep since we have only a one-MCU buffer.
146
 * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED.
147
 *
148
 * NB: output_buf contains a plane for each component in image,
149
 * which we index according to the component's SOF position.
150
 */
151
152
METHODDEF(int)
153
decompress_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
154
0
{
155
0
  j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
156
0
  d_diff_ptr diff = (d_diff_ptr) losslsd->diff_private;
157
0
  JDIMENSION MCU_col_num;   /* index of current MCU within row */
158
0
  JDIMENSION MCU_count;     /* number of MCUs decoded */
159
0
  JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
160
0
  int comp, ci, row, prev_row;
161
0
  unsigned int yoffset;
162
0
  jpeg_component_info *compptr;
163
164
  /* Loop to process as much as one whole iMCU row */
165
0
  for (yoffset = diff->MCU_vert_offset; yoffset < diff->MCU_rows_per_iMCU_row;
166
0
       yoffset++) {
167
168
    /* Process restart marker if needed; may have to suspend */
169
0
    if (cinfo->restart_interval) {
170
0
      if (diff->restart_rows_to_go == 0)
171
0
    if (! process_restart(cinfo))
172
0
      return JPEG_SUSPENDED;
173
0
    }
174
175
0
    MCU_col_num = diff->MCU_ctr;
176
    /* Try to fetch an MCU-row (or remaining portion of suspended MCU-row). */
177
0
    MCU_count =
178
0
      (*losslsd->entropy_decode_mcus) (cinfo,
179
0
                       diff->diff_buf, yoffset, MCU_col_num,
180
0
                       cinfo->MCUs_per_row - MCU_col_num);
181
0
    if (MCU_count != cinfo->MCUs_per_row - MCU_col_num) {
182
      /* Suspension forced; update state counters and exit */
183
0
      diff->MCU_vert_offset = yoffset;
184
0
      diff->MCU_ctr += MCU_count;
185
0
      return JPEG_SUSPENDED;
186
0
    }
187
188
    /* Account for restart interval (no-op if not using restarts) */
189
0
    diff->restart_rows_to_go--;
190
191
    /* Completed an MCU row, but perhaps not an iMCU row */
192
0
    diff->MCU_ctr = 0;
193
0
  }
194
195
  /*
196
   * Undifference and scale each scanline of the disassembled MCU-row
197
   * separately.  We do not process dummy samples at the end of a scanline
198
   * or dummy rows at the end of the image.
199
   */
200
0
  for (comp = 0; comp < cinfo->comps_in_scan; comp++) {
201
0
    compptr = cinfo->cur_comp_info[comp];
202
0
    ci = compptr->component_index;
203
0
    for (row = 0, prev_row = compptr->v_samp_factor - 1;
204
0
     row < (cinfo->input_iMCU_row == last_iMCU_row ?
205
0
        compptr->last_row_height : compptr->v_samp_factor);
206
0
     prev_row = row, row++) {
207
0
      (*losslsd->predict_undifference[ci]) (cinfo, ci,
208
0
                        diff->diff_buf[ci][row],
209
0
                        diff->undiff_buf[ci][prev_row],
210
0
                        diff->undiff_buf[ci][row],
211
0
                        compptr->width_in_data_units);
212
0
      (*losslsd->scaler_scale) (cinfo, diff->undiff_buf[ci][row],
213
0
                output_buf[ci][row],
214
0
                compptr->width_in_data_units);
215
0
    }
216
0
  }
217
218
  /* Completed the iMCU row, advance counters for next one.
219
   *
220
   * NB: output_data will increment output_iMCU_row.
221
   * This counter is not needed for the single-pass case
222
   * or the input side of the multi-pass case.
223
   */
224
0
  if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) {
225
0
    start_iMCU_row(cinfo);
226
0
    return JPEG_ROW_COMPLETED;
227
0
  }
228
  /* Completed the scan */
229
0
  (*cinfo->inputctl->finish_input_pass) (cinfo);
230
0
  return JPEG_SCAN_COMPLETED;
231
0
}
232
233
234
/*
235
 * Dummy consume-input routine for single-pass operation.
236
 */
237
238
METHODDEF(int)
239
dummy_consume_data (j_decompress_ptr cinfo)
240
0
{
241
0
  (void)cinfo;
242
0
  return JPEG_SUSPENDED;    /* Always indicate nothing was done */
243
0
}
244
245
246
#ifdef D_MULTISCAN_FILES_SUPPORTED
247
248
/*
249
 * Consume input data and store it in the full-image sample buffer.
250
 * We read as much as one fully interleaved MCU row ("iMCU" row) per call,
251
 * ie, v_samp_factor rows for each component in the scan.
252
 * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED.
253
 */
254
255
METHODDEF(int)
256
consume_data (j_decompress_ptr cinfo)
257
0
{
258
0
  j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
259
0
  d_diff_ptr diff = (d_diff_ptr) losslsd->diff_private;
260
  /* JDIMENSION MCU_col_num; */ /* index of current MCU within row */
261
  /* JDIMENSION MCU_count; */   /* number of MCUs decoded */
262
  /* JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; */
263
0
  int comp, ci /* , yoffset, row, prev_row */;
264
0
  JSAMPARRAY buffer[MAX_COMPONENTS];
265
0
  jpeg_component_info *compptr;
266
267
  /* Align the virtual buffers for the components used in this scan. */
268
0
  for (comp = 0; comp < cinfo->comps_in_scan; comp++) {
269
0
    compptr = cinfo->cur_comp_info[comp];
270
0
    ci = compptr->component_index;
271
0
    buffer[ci] = (*cinfo->mem->access_virt_sarray)
272
0
      ((j_common_ptr) cinfo, diff->whole_image[ci],
273
0
       cinfo->input_iMCU_row * (JDIMENSION)compptr->v_samp_factor,
274
0
       (JDIMENSION) compptr->v_samp_factor, TRUE);
275
0
  }
276
277
0
  return decompress_data(cinfo, buffer);
278
0
}
279
280
281
/*
282
 * Output some data from the full-image buffer sample in the multi-pass case.
283
 * Always attempts to emit one fully interleaved MCU row ("iMCU" row).
284
 * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED.
285
 *
286
 * NB: output_buf contains a plane for each component in image.
287
 */
288
289
METHODDEF(int)
290
output_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
291
0
{
292
0
  j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
293
0
  d_diff_ptr diff = (d_diff_ptr) losslsd->diff_private;
294
0
  JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
295
0
  int ci, samp_rows, row;
296
0
  JSAMPARRAY buffer;
297
0
  jpeg_component_info *compptr;
298
299
  /* Force some input to be done if we are getting ahead of the input. */
300
0
  while (cinfo->input_scan_number < cinfo->output_scan_number ||
301
0
     (cinfo->input_scan_number == cinfo->output_scan_number &&
302
0
      cinfo->input_iMCU_row <= cinfo->output_iMCU_row)) {
303
0
    if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED)
304
0
      return JPEG_SUSPENDED;
305
0
  }
306
307
  /* OK, output from the virtual arrays. */
308
0
  for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
309
0
       ci++, compptr++) {
310
    /* Align the virtual buffer for this component. */
311
0
    buffer = (*cinfo->mem->access_virt_sarray)
312
0
      ((j_common_ptr) cinfo, diff->whole_image[ci],
313
0
       cinfo->output_iMCU_row * (JDIMENSION)compptr->v_samp_factor,
314
0
       (JDIMENSION) compptr->v_samp_factor, FALSE);
315
316
0
    if (cinfo->output_iMCU_row < last_iMCU_row)
317
0
      samp_rows = compptr->v_samp_factor;
318
0
    else {
319
      /* NB: can't use last_row_height here; it is input-side-dependent! */
320
0
      samp_rows = (int)compptr->height_in_data_units % compptr->v_samp_factor;
321
0
      if (samp_rows == 0) samp_rows = compptr->v_samp_factor;
322
0
    }
323
324
0
    for (row = 0; row < samp_rows; row++) {
325
0
      MEMCOPY(output_buf[ci][row], buffer[row],
326
0
          compptr->width_in_data_units * SIZEOF(JSAMPLE));
327
0
    }
328
0
  }
329
330
0
  if (++(cinfo->output_iMCU_row) < cinfo->total_iMCU_rows)
331
0
    return JPEG_ROW_COMPLETED;
332
0
  return JPEG_SCAN_COMPLETED;
333
0
}
334
335
#endif /* D_MULTISCAN_FILES_SUPPORTED */
336
337
338
/*
339
 * Initialize difference buffer controller.
340
 */
341
342
GLOBAL(void)
343
jinit_d_diff_controller (j_decompress_ptr cinfo, boolean need_full_buffer)
344
0
{
345
0
  j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
346
0
  d_diff_ptr diff;
347
0
  int ci;
348
0
  jpeg_component_info *compptr;
349
350
0
  diff = (d_diff_ptr)
351
0
    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
352
0
                SIZEOF(d_diff_controller));
353
0
  losslsd->diff_private = (void *) diff;
354
0
  losslsd->diff_start_input_pass = start_input_pass;
355
0
  losslsd->pub.start_output_pass = start_output_pass;
356
357
  /* Create the [un]difference buffers. */
358
0
  for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
359
0
       ci++, compptr++) {
360
0
    diff->diff_buf[ci] = (*cinfo->mem->alloc_darray)
361
0
      ((j_common_ptr) cinfo, JPOOL_IMAGE,
362
0
       (JDIMENSION) jround_up((long) compptr->width_in_data_units,
363
0
                  (long) compptr->h_samp_factor),
364
0
       (JDIMENSION) compptr->v_samp_factor);
365
0
    diff->undiff_buf[ci] = (*cinfo->mem->alloc_darray)
366
0
      ((j_common_ptr) cinfo, JPOOL_IMAGE,
367
0
       (JDIMENSION) jround_up((long) compptr->width_in_data_units,
368
0
                  (long) compptr->h_samp_factor),
369
0
       (JDIMENSION) compptr->v_samp_factor);
370
0
  }
371
372
0
  if (need_full_buffer) {
373
0
#ifdef D_MULTISCAN_FILES_SUPPORTED
374
    /* Allocate a full-image virtual array for each component. */
375
0
    int access_rows;
376
377
0
    for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
378
0
     ci++, compptr++) {
379
0
      access_rows = compptr->v_samp_factor;
380
0
      diff->whole_image[ci] = (*cinfo->mem->request_virt_sarray)
381
0
    ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
382
0
     (JDIMENSION) jround_up((long) compptr->width_in_data_units,
383
0
                (long) compptr->h_samp_factor),
384
0
     (JDIMENSION) jround_up((long) compptr->height_in_data_units,
385
0
                (long) compptr->v_samp_factor),
386
0
     (JDIMENSION) access_rows);
387
0
    }
388
0
    losslsd->pub.consume_data = consume_data;
389
0
    losslsd->pub.decompress_data = output_data;
390
#else
391
    ERREXIT(cinfo, JERR_NOT_COMPILED);
392
#endif
393
0
  } else {
394
0
    losslsd->pub.consume_data = dummy_consume_data;
395
0
    losslsd->pub.decompress_data = decompress_data;
396
    diff->whole_image[0] = NULL; /* flag for no virtual arrays */
397
0
  }
398
0
}
399
400
#endif /* D_LOSSLESS_SUPPORTED */