Coverage Report

Created: 2025-10-10 07:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libjpeg-turbo.dev/src/jcapimin.c
Line
Count
Source
1
/*
2
 * jcapimin.c
3
 *
4
 * This file was part of the Independent JPEG Group's software:
5
 * Copyright (C) 1994-1998, Thomas G. Lane.
6
 * Modified 2003-2010 by Guido Vollbeding.
7
 * libjpeg-turbo Modifications:
8
 * Copyright (C) 2022, 2024-2025, D. R. Commander.
9
 * For conditions of distribution and use, see the accompanying README.ijg
10
 * file.
11
 *
12
 * This file contains application interface code for the compression half
13
 * of the JPEG library.  These are the "minimum" API routines that may be
14
 * needed in either the normal full-compression case or the transcoding-only
15
 * case.
16
 *
17
 * Most of the routines intended to be called directly by an application
18
 * are in this file or in jcapistd.c.  But also see jcparam.c for
19
 * parameter-setup helper routines, jcomapi.c for routines shared by
20
 * compression and decompression, and jctrans.c for the transcoding case.
21
 */
22
23
#define JPEG_INTERNALS
24
#include "jinclude.h"
25
#include "jpeglib.h"
26
#include "jcmaster.h"
27
#ifdef WITH_SIMD
28
#include "../simd/jsimdconst.h"
29
#endif
30
31
32
/*
33
 * Initialization of a JPEG compression object.
34
 * The error manager must already be set up (in case memory manager fails).
35
 */
36
37
GLOBAL(void)
38
jpeg_CreateCompress(j_compress_ptr cinfo, int version, size_t structsize)
39
22.7k
{
40
22.7k
  int i;
41
42
  /* Guard against version mismatches between library and caller. */
43
22.7k
  cinfo->mem = NULL;            /* so jpeg_destroy knows mem mgr not called */
44
22.7k
  if (version != JPEG_LIB_VERSION)
45
0
    ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version);
46
22.7k
  if (structsize != sizeof(struct jpeg_compress_struct))
47
0
    ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE,
48
22.7k
             (int)sizeof(struct jpeg_compress_struct), (int)structsize);
49
50
  /* For debugging purposes, we zero the whole master structure.
51
   * But the application has already set the err pointer, and may have set
52
   * client_data, so we have to save and restore those fields.
53
   * Note: if application hasn't set client_data, tools like Purify may
54
   * complain here.
55
   */
56
22.7k
  {
57
22.7k
    struct jpeg_error_mgr *err = cinfo->err;
58
22.7k
    void *client_data = cinfo->client_data; /* ignore Purify complaint here */
59
22.7k
    memset(cinfo, 0, sizeof(struct jpeg_compress_struct));
60
22.7k
    cinfo->err = err;
61
22.7k
    cinfo->client_data = client_data;
62
22.7k
  }
63
22.7k
  cinfo->is_decompressor = FALSE;
64
65
  /* Initialize a memory manager instance for this object */
66
22.7k
  jinit_memory_mgr((j_common_ptr)cinfo);
67
68
  /* Zero out pointers to permanent structures. */
69
22.7k
  cinfo->progress = NULL;
70
22.7k
  cinfo->dest = NULL;
71
72
22.7k
  cinfo->comp_info = NULL;
73
74
113k
  for (i = 0; i < NUM_QUANT_TBLS; i++) {
75
91.0k
    cinfo->quant_tbl_ptrs[i] = NULL;
76
#if JPEG_LIB_VERSION >= 70
77
    cinfo->q_scale_factor[i] = 100;
78
#endif
79
91.0k
  }
80
81
113k
  for (i = 0; i < NUM_HUFF_TBLS; i++) {
82
91.0k
    cinfo->dc_huff_tbl_ptrs[i] = NULL;
83
91.0k
    cinfo->ac_huff_tbl_ptrs[i] = NULL;
84
91.0k
  }
85
86
#if JPEG_LIB_VERSION >= 80
87
  /* Must do it here for emit_dqt in case jpeg_write_tables is used */
88
  cinfo->block_size = DCTSIZE;
89
  cinfo->natural_order = jpeg_natural_order;
90
  cinfo->lim_Se = DCTSIZE2 - 1;
91
#endif
92
93
22.7k
  cinfo->script_space = NULL;
94
95
22.7k
  cinfo->input_gamma = 1.0;     /* in case application forgets */
96
97
22.7k
  cinfo->data_precision = BITS_IN_JSAMPLE;
98
99
  /* OK, I'm ready */
100
22.7k
  cinfo->global_state = CSTATE_START;
101
102
  /* The master struct is used to store extension parameters, so we allocate it
103
   * here.
104
   */
105
22.7k
  cinfo->master = (struct jpeg_comp_master *)
106
22.7k
      (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_PERMANENT,
107
22.7k
                                  sizeof(my_comp_master));
108
22.7k
  memset(cinfo->master, 0, sizeof(my_comp_master));
109
22.7k
#ifdef WITH_SIMD
110
22.7k
  cinfo->master->simd_support = JSIMD_UNDEFINED;
111
22.7k
  cinfo->master->simd_huffman = 1;
112
22.7k
#endif
113
22.7k
}
114
115
116
/*
117
 * Destruction of a JPEG compression object
118
 */
119
120
GLOBAL(void)
121
jpeg_destroy_compress(j_compress_ptr cinfo)
122
22.7k
{
123
22.7k
  jpeg_destroy((j_common_ptr)cinfo); /* use common routine */
124
22.7k
}
125
126
127
/*
128
 * Abort processing of a JPEG compression operation,
129
 * but don't destroy the object itself.
130
 */
131
132
GLOBAL(void)
133
jpeg_abort_compress(j_compress_ptr cinfo)
134
10.2k
{
135
10.2k
  jpeg_abort((j_common_ptr)cinfo); /* use common routine */
136
10.2k
}
137
138
139
/*
140
 * Forcibly suppress or un-suppress all quantization and Huffman tables.
141
 * Marks all currently defined tables as already written (if suppress)
142
 * or not written (if !suppress).  This will control whether they get emitted
143
 * by a subsequent jpeg_start_compress call.
144
 *
145
 * This routine is exported for use by applications that want to produce
146
 * abbreviated JPEG datastreams.  It logically belongs in jcparam.c, but
147
 * since it is called by jpeg_start_compress, we put it here --- otherwise
148
 * jcparam.o would be linked whether the application used it or not.
149
 */
150
151
GLOBAL(void)
152
jpeg_suppress_tables(j_compress_ptr cinfo, boolean suppress)
153
10.2k
{
154
10.2k
  int i;
155
10.2k
  JQUANT_TBL *qtbl;
156
10.2k
  JHUFF_TBL *htbl;
157
158
51.0k
  for (i = 0; i < NUM_QUANT_TBLS; i++) {
159
40.8k
    if ((qtbl = cinfo->quant_tbl_ptrs[i]) != NULL)
160
20.4k
      qtbl->sent_table = suppress;
161
40.8k
  }
162
163
51.0k
  for (i = 0; i < NUM_HUFF_TBLS; i++) {
164
40.8k
    if ((htbl = cinfo->dc_huff_tbl_ptrs[i]) != NULL)
165
20.4k
      htbl->sent_table = suppress;
166
40.8k
    if ((htbl = cinfo->ac_huff_tbl_ptrs[i]) != NULL)
167
20.4k
      htbl->sent_table = suppress;
168
40.8k
  }
169
10.2k
}
170
171
172
/*
173
 * Finish JPEG compression.
174
 *
175
 * If a multipass operating mode was selected, this may do a great deal of
176
 * work including most of the actual output.
177
 */
178
179
GLOBAL(void)
180
jpeg_finish_compress(j_compress_ptr cinfo)
181
10.2k
{
182
10.2k
  JDIMENSION iMCU_row;
183
184
10.2k
  if (cinfo->global_state == CSTATE_SCANNING ||
185
10.2k
      cinfo->global_state == CSTATE_RAW_OK) {
186
    /* Terminate first pass */
187
10.2k
    if (cinfo->next_scanline < cinfo->image_height)
188
0
      ERREXIT(cinfo, JERR_TOO_LITTLE_DATA);
189
10.2k
    (*cinfo->master->finish_pass) (cinfo);
190
10.2k
  } else if (cinfo->global_state != CSTATE_WRCOEFS)
191
0
    ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
192
  /* Perform any remaining passes */
193
59.1k
  while (!cinfo->master->is_last_pass) {
194
48.9k
    (*cinfo->master->prepare_for_pass) (cinfo);
195
20.0M
    for (iMCU_row = 0; iMCU_row < cinfo->total_iMCU_rows; iMCU_row++) {
196
19.9M
      if (cinfo->progress != NULL) {
197
0
        cinfo->progress->pass_counter = (long)iMCU_row;
198
0
        cinfo->progress->pass_limit = (long)cinfo->total_iMCU_rows;
199
0
        (*cinfo->progress->progress_monitor) ((j_common_ptr)cinfo);
200
0
      }
201
      /* We bypass the main controller and invoke coef controller directly;
202
       * all work is being done from the coefficient buffer.
203
       */
204
19.9M
      if (cinfo->data_precision <= 8) {
205
19.9M
        if (cinfo->coef->compress_data == NULL)
206
0
          ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
207
19.9M
        if (!(*cinfo->coef->compress_data) (cinfo, (JSAMPIMAGE)NULL))
208
0
          ERREXIT(cinfo, JERR_CANT_SUSPEND);
209
19.9M
      } else if (cinfo->data_precision <= 12) {
210
0
        if (cinfo->coef->compress_data_12 == NULL)
211
0
          ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
212
0
        if (!(*cinfo->coef->compress_data_12) (cinfo, (J12SAMPIMAGE)NULL))
213
0
          ERREXIT(cinfo, JERR_CANT_SUSPEND);
214
0
      } else {
215
0
#ifdef C_LOSSLESS_SUPPORTED
216
0
        if (cinfo->coef->compress_data_16 == NULL)
217
0
          ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
218
0
        if (!(*cinfo->coef->compress_data_16) (cinfo, (J16SAMPIMAGE)NULL))
219
0
          ERREXIT(cinfo, JERR_CANT_SUSPEND);
220
#else
221
        ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
222
#endif
223
0
      }
224
19.9M
    }
225
48.9k
    (*cinfo->master->finish_pass) (cinfo);
226
48.9k
  }
227
  /* Write EOI, do final cleanup */
228
10.2k
  (*cinfo->marker->write_file_trailer) (cinfo);
229
10.2k
  (*cinfo->dest->term_destination) (cinfo);
230
  /* We can use jpeg_abort to release memory and reset global_state */
231
10.2k
  jpeg_abort((j_common_ptr)cinfo);
232
10.2k
}
233
234
235
/*
236
 * Write a special marker.
237
 * This is only recommended for writing COM or APPn markers.
238
 * Must be called after jpeg_start_compress() and before
239
 * first call to jpeg_write_scanlines() or jpeg_write_raw_data().
240
 */
241
242
GLOBAL(void)
243
jpeg_write_marker(j_compress_ptr cinfo, int marker, const JOCTET *dataptr,
244
                  unsigned int datalen)
245
0
{
246
0
  void (*write_marker_byte) (j_compress_ptr info, int val);
247
248
0
  if (cinfo->next_scanline != 0 ||
249
0
      (cinfo->global_state != CSTATE_SCANNING &&
250
0
       cinfo->global_state != CSTATE_RAW_OK &&
251
0
       cinfo->global_state != CSTATE_WRCOEFS))
252
0
    ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
253
254
0
  (*cinfo->marker->write_marker_header) (cinfo, marker, datalen);
255
0
  write_marker_byte = cinfo->marker->write_marker_byte; /* copy for speed */
256
0
  while (datalen--) {
257
0
    (*write_marker_byte) (cinfo, *dataptr);
258
0
    dataptr++;
259
0
  }
260
0
}
261
262
/* Same, but piecemeal. */
263
264
GLOBAL(void)
265
jpeg_write_m_header(j_compress_ptr cinfo, int marker, unsigned int datalen)
266
0
{
267
0
  if (cinfo->next_scanline != 0 ||
268
0
      (cinfo->global_state != CSTATE_SCANNING &&
269
0
       cinfo->global_state != CSTATE_RAW_OK &&
270
0
       cinfo->global_state != CSTATE_WRCOEFS))
271
0
    ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
272
273
0
  (*cinfo->marker->write_marker_header) (cinfo, marker, datalen);
274
0
}
275
276
GLOBAL(void)
277
jpeg_write_m_byte(j_compress_ptr cinfo, int val)
278
0
{
279
0
  (*cinfo->marker->write_marker_byte) (cinfo, val);
280
0
}
281
282
283
/*
284
 * Alternate compression function: just write an abbreviated table file.
285
 * Before calling this, all parameters and a data destination must be set up.
286
 *
287
 * To produce a pair of files containing abbreviated tables and abbreviated
288
 * image data, one would proceed as follows:
289
 *
290
 *              initialize JPEG object
291
 *              set JPEG parameters
292
 *              set destination to table file
293
 *              jpeg_write_tables(cinfo);
294
 *              set destination to image file
295
 *              jpeg_start_compress(cinfo, FALSE);
296
 *              write data...
297
 *              jpeg_finish_compress(cinfo);
298
 *
299
 * jpeg_write_tables has the side effect of marking all tables written
300
 * (same as jpeg_suppress_tables(..., TRUE)).  Thus a subsequent start_compress
301
 * will not re-emit the tables unless it is passed write_all_tables=TRUE.
302
 */
303
304
GLOBAL(void)
305
jpeg_write_tables(j_compress_ptr cinfo)
306
0
{
307
0
  if (cinfo->global_state != CSTATE_START)
308
0
    ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
309
310
  /* (Re)initialize error mgr and destination modules */
311
0
  (*cinfo->err->reset_error_mgr) ((j_common_ptr)cinfo);
312
0
  (*cinfo->dest->init_destination) (cinfo);
313
  /* Initialize the marker writer ... bit of a crock to do it here. */
314
0
  jinit_marker_writer(cinfo);
315
  /* Write them tables! */
316
0
  (*cinfo->marker->write_tables_only) (cinfo);
317
  /* And clean up. */
318
0
  (*cinfo->dest->term_destination) (cinfo);
319
  /*
320
   * In library releases up through v6a, we called jpeg_abort() here to free
321
   * any working memory allocated by the destination manager and marker
322
   * writer.  Some applications had a problem with that: they allocated space
323
   * of their own from the library memory manager, and didn't want it to go
324
   * away during write_tables.  So now we do nothing.  This will cause a
325
   * memory leak if an app calls write_tables repeatedly without doing a full
326
   * compression cycle or otherwise resetting the JPEG object.  However, that
327
   * seems less bad than unexpectedly freeing memory in the normal case.
328
   * An app that prefers the old behavior can call jpeg_abort for itself after
329
   * each call to jpeg_write_tables().
330
   */
331
0
}