xref: /aosp_15_r20/external/libjpeg-turbo/jcapistd.c (revision dfc6aa5c1cfd4bc4e2018dc74aa96e29ee49c6da)
1*dfc6aa5cSAndroid Build Coastguard Worker /*
2*dfc6aa5cSAndroid Build Coastguard Worker  * jcapistd.c
3*dfc6aa5cSAndroid Build Coastguard Worker  *
4*dfc6aa5cSAndroid Build Coastguard Worker  * Copyright (C) 1994-1996, Thomas G. Lane.
5*dfc6aa5cSAndroid Build Coastguard Worker  * This file is part of the Independent JPEG Group's software.
6*dfc6aa5cSAndroid Build Coastguard Worker  * For conditions of distribution and use, see the accompanying README.ijg
7*dfc6aa5cSAndroid Build Coastguard Worker  * file.
8*dfc6aa5cSAndroid Build Coastguard Worker  *
9*dfc6aa5cSAndroid Build Coastguard Worker  * This file contains application interface code for the compression half
10*dfc6aa5cSAndroid Build Coastguard Worker  * of the JPEG library.  These are the "standard" API routines that are
11*dfc6aa5cSAndroid Build Coastguard Worker  * used in the normal full-compression case.  They are not used by a
12*dfc6aa5cSAndroid Build Coastguard Worker  * transcoding-only application.  Note that if an application links in
13*dfc6aa5cSAndroid Build Coastguard Worker  * jpeg_start_compress, it will end up linking in the entire compressor.
14*dfc6aa5cSAndroid Build Coastguard Worker  * We thus must separate this file from jcapimin.c to avoid linking the
15*dfc6aa5cSAndroid Build Coastguard Worker  * whole compression library into a transcoder.
16*dfc6aa5cSAndroid Build Coastguard Worker  */
17*dfc6aa5cSAndroid Build Coastguard Worker 
18*dfc6aa5cSAndroid Build Coastguard Worker #define JPEG_INTERNALS
19*dfc6aa5cSAndroid Build Coastguard Worker #include "jinclude.h"
20*dfc6aa5cSAndroid Build Coastguard Worker #include "jpeglib.h"
21*dfc6aa5cSAndroid Build Coastguard Worker 
22*dfc6aa5cSAndroid Build Coastguard Worker 
23*dfc6aa5cSAndroid Build Coastguard Worker /*
24*dfc6aa5cSAndroid Build Coastguard Worker  * Compression initialization.
25*dfc6aa5cSAndroid Build Coastguard Worker  * Before calling this, all parameters and a data destination must be set up.
26*dfc6aa5cSAndroid Build Coastguard Worker  *
27*dfc6aa5cSAndroid Build Coastguard Worker  * We require a write_all_tables parameter as a failsafe check when writing
28*dfc6aa5cSAndroid Build Coastguard Worker  * multiple datastreams from the same compression object.  Since prior runs
29*dfc6aa5cSAndroid Build Coastguard Worker  * will have left all the tables marked sent_table=TRUE, a subsequent run
30*dfc6aa5cSAndroid Build Coastguard Worker  * would emit an abbreviated stream (no tables) by default.  This may be what
31*dfc6aa5cSAndroid Build Coastguard Worker  * is wanted, but for safety's sake it should not be the default behavior:
32*dfc6aa5cSAndroid Build Coastguard Worker  * programmers should have to make a deliberate choice to emit abbreviated
33*dfc6aa5cSAndroid Build Coastguard Worker  * images.  Therefore the documentation and examples should encourage people
34*dfc6aa5cSAndroid Build Coastguard Worker  * to pass write_all_tables=TRUE; then it will take active thought to do the
35*dfc6aa5cSAndroid Build Coastguard Worker  * wrong thing.
36*dfc6aa5cSAndroid Build Coastguard Worker  */
37*dfc6aa5cSAndroid Build Coastguard Worker 
38*dfc6aa5cSAndroid Build Coastguard Worker GLOBAL(void)
jpeg_start_compress(j_compress_ptr cinfo,boolean write_all_tables)39*dfc6aa5cSAndroid Build Coastguard Worker jpeg_start_compress(j_compress_ptr cinfo, boolean write_all_tables)
40*dfc6aa5cSAndroid Build Coastguard Worker {
41*dfc6aa5cSAndroid Build Coastguard Worker   if (cinfo->global_state != CSTATE_START)
42*dfc6aa5cSAndroid Build Coastguard Worker     ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
43*dfc6aa5cSAndroid Build Coastguard Worker 
44*dfc6aa5cSAndroid Build Coastguard Worker   if (write_all_tables)
45*dfc6aa5cSAndroid Build Coastguard Worker     jpeg_suppress_tables(cinfo, FALSE); /* mark all tables to be written */
46*dfc6aa5cSAndroid Build Coastguard Worker 
47*dfc6aa5cSAndroid Build Coastguard Worker   /* (Re)initialize error mgr and destination modules */
48*dfc6aa5cSAndroid Build Coastguard Worker   (*cinfo->err->reset_error_mgr) ((j_common_ptr)cinfo);
49*dfc6aa5cSAndroid Build Coastguard Worker   (*cinfo->dest->init_destination) (cinfo);
50*dfc6aa5cSAndroid Build Coastguard Worker   /* Perform master selection of active modules */
51*dfc6aa5cSAndroid Build Coastguard Worker   jinit_compress_master(cinfo);
52*dfc6aa5cSAndroid Build Coastguard Worker   /* Set up for the first pass */
53*dfc6aa5cSAndroid Build Coastguard Worker   (*cinfo->master->prepare_for_pass) (cinfo);
54*dfc6aa5cSAndroid Build Coastguard Worker   /* Ready for application to drive first pass through jpeg_write_scanlines
55*dfc6aa5cSAndroid Build Coastguard Worker    * or jpeg_write_raw_data.
56*dfc6aa5cSAndroid Build Coastguard Worker    */
57*dfc6aa5cSAndroid Build Coastguard Worker   cinfo->next_scanline = 0;
58*dfc6aa5cSAndroid Build Coastguard Worker   cinfo->global_state = (cinfo->raw_data_in ? CSTATE_RAW_OK : CSTATE_SCANNING);
59*dfc6aa5cSAndroid Build Coastguard Worker }
60*dfc6aa5cSAndroid Build Coastguard Worker 
61*dfc6aa5cSAndroid Build Coastguard Worker 
62*dfc6aa5cSAndroid Build Coastguard Worker /*
63*dfc6aa5cSAndroid Build Coastguard Worker  * Write some scanlines of data to the JPEG compressor.
64*dfc6aa5cSAndroid Build Coastguard Worker  *
65*dfc6aa5cSAndroid Build Coastguard Worker  * The return value will be the number of lines actually written.
66*dfc6aa5cSAndroid Build Coastguard Worker  * This should be less than the supplied num_lines only in case that
67*dfc6aa5cSAndroid Build Coastguard Worker  * the data destination module has requested suspension of the compressor,
68*dfc6aa5cSAndroid Build Coastguard Worker  * or if more than image_height scanlines are passed in.
69*dfc6aa5cSAndroid Build Coastguard Worker  *
70*dfc6aa5cSAndroid Build Coastguard Worker  * Note: we warn about excess calls to jpeg_write_scanlines() since
71*dfc6aa5cSAndroid Build Coastguard Worker  * this likely signals an application programmer error.  However,
72*dfc6aa5cSAndroid Build Coastguard Worker  * excess scanlines passed in the last valid call are *silently* ignored,
73*dfc6aa5cSAndroid Build Coastguard Worker  * so that the application need not adjust num_lines for end-of-image
74*dfc6aa5cSAndroid Build Coastguard Worker  * when using a multiple-scanline buffer.
75*dfc6aa5cSAndroid Build Coastguard Worker  */
76*dfc6aa5cSAndroid Build Coastguard Worker 
77*dfc6aa5cSAndroid Build Coastguard Worker GLOBAL(JDIMENSION)
jpeg_write_scanlines(j_compress_ptr cinfo,JSAMPARRAY scanlines,JDIMENSION num_lines)78*dfc6aa5cSAndroid Build Coastguard Worker jpeg_write_scanlines(j_compress_ptr cinfo, JSAMPARRAY scanlines,
79*dfc6aa5cSAndroid Build Coastguard Worker                      JDIMENSION num_lines)
80*dfc6aa5cSAndroid Build Coastguard Worker {
81*dfc6aa5cSAndroid Build Coastguard Worker   JDIMENSION row_ctr, rows_left;
82*dfc6aa5cSAndroid Build Coastguard Worker 
83*dfc6aa5cSAndroid Build Coastguard Worker   if (cinfo->global_state != CSTATE_SCANNING)
84*dfc6aa5cSAndroid Build Coastguard Worker     ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
85*dfc6aa5cSAndroid Build Coastguard Worker   if (cinfo->next_scanline >= cinfo->image_height)
86*dfc6aa5cSAndroid Build Coastguard Worker     WARNMS(cinfo, JWRN_TOO_MUCH_DATA);
87*dfc6aa5cSAndroid Build Coastguard Worker 
88*dfc6aa5cSAndroid Build Coastguard Worker   /* Call progress monitor hook if present */
89*dfc6aa5cSAndroid Build Coastguard Worker   if (cinfo->progress != NULL) {
90*dfc6aa5cSAndroid Build Coastguard Worker     cinfo->progress->pass_counter = (long)cinfo->next_scanline;
91*dfc6aa5cSAndroid Build Coastguard Worker     cinfo->progress->pass_limit = (long)cinfo->image_height;
92*dfc6aa5cSAndroid Build Coastguard Worker     (*cinfo->progress->progress_monitor) ((j_common_ptr)cinfo);
93*dfc6aa5cSAndroid Build Coastguard Worker   }
94*dfc6aa5cSAndroid Build Coastguard Worker 
95*dfc6aa5cSAndroid Build Coastguard Worker   /* Give master control module another chance if this is first call to
96*dfc6aa5cSAndroid Build Coastguard Worker    * jpeg_write_scanlines.  This lets output of the frame/scan headers be
97*dfc6aa5cSAndroid Build Coastguard Worker    * delayed so that application can write COM, etc, markers between
98*dfc6aa5cSAndroid Build Coastguard Worker    * jpeg_start_compress and jpeg_write_scanlines.
99*dfc6aa5cSAndroid Build Coastguard Worker    */
100*dfc6aa5cSAndroid Build Coastguard Worker   if (cinfo->master->call_pass_startup)
101*dfc6aa5cSAndroid Build Coastguard Worker     (*cinfo->master->pass_startup) (cinfo);
102*dfc6aa5cSAndroid Build Coastguard Worker 
103*dfc6aa5cSAndroid Build Coastguard Worker   /* Ignore any extra scanlines at bottom of image. */
104*dfc6aa5cSAndroid Build Coastguard Worker   rows_left = cinfo->image_height - cinfo->next_scanline;
105*dfc6aa5cSAndroid Build Coastguard Worker   if (num_lines > rows_left)
106*dfc6aa5cSAndroid Build Coastguard Worker     num_lines = rows_left;
107*dfc6aa5cSAndroid Build Coastguard Worker 
108*dfc6aa5cSAndroid Build Coastguard Worker   row_ctr = 0;
109*dfc6aa5cSAndroid Build Coastguard Worker   (*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, num_lines);
110*dfc6aa5cSAndroid Build Coastguard Worker   cinfo->next_scanline += row_ctr;
111*dfc6aa5cSAndroid Build Coastguard Worker   return row_ctr;
112*dfc6aa5cSAndroid Build Coastguard Worker }
113*dfc6aa5cSAndroid Build Coastguard Worker 
114*dfc6aa5cSAndroid Build Coastguard Worker 
115*dfc6aa5cSAndroid Build Coastguard Worker /*
116*dfc6aa5cSAndroid Build Coastguard Worker  * Alternate entry point to write raw data.
117*dfc6aa5cSAndroid Build Coastguard Worker  * Processes exactly one iMCU row per call, unless suspended.
118*dfc6aa5cSAndroid Build Coastguard Worker  */
119*dfc6aa5cSAndroid Build Coastguard Worker 
120*dfc6aa5cSAndroid Build Coastguard Worker GLOBAL(JDIMENSION)
jpeg_write_raw_data(j_compress_ptr cinfo,JSAMPIMAGE data,JDIMENSION num_lines)121*dfc6aa5cSAndroid Build Coastguard Worker jpeg_write_raw_data(j_compress_ptr cinfo, JSAMPIMAGE data,
122*dfc6aa5cSAndroid Build Coastguard Worker                     JDIMENSION num_lines)
123*dfc6aa5cSAndroid Build Coastguard Worker {
124*dfc6aa5cSAndroid Build Coastguard Worker   JDIMENSION lines_per_iMCU_row;
125*dfc6aa5cSAndroid Build Coastguard Worker 
126*dfc6aa5cSAndroid Build Coastguard Worker   if (cinfo->global_state != CSTATE_RAW_OK)
127*dfc6aa5cSAndroid Build Coastguard Worker     ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
128*dfc6aa5cSAndroid Build Coastguard Worker   if (cinfo->next_scanline >= cinfo->image_height) {
129*dfc6aa5cSAndroid Build Coastguard Worker     WARNMS(cinfo, JWRN_TOO_MUCH_DATA);
130*dfc6aa5cSAndroid Build Coastguard Worker     return 0;
131*dfc6aa5cSAndroid Build Coastguard Worker   }
132*dfc6aa5cSAndroid Build Coastguard Worker 
133*dfc6aa5cSAndroid Build Coastguard Worker   /* Call progress monitor hook if present */
134*dfc6aa5cSAndroid Build Coastguard Worker   if (cinfo->progress != NULL) {
135*dfc6aa5cSAndroid Build Coastguard Worker     cinfo->progress->pass_counter = (long)cinfo->next_scanline;
136*dfc6aa5cSAndroid Build Coastguard Worker     cinfo->progress->pass_limit = (long)cinfo->image_height;
137*dfc6aa5cSAndroid Build Coastguard Worker     (*cinfo->progress->progress_monitor) ((j_common_ptr)cinfo);
138*dfc6aa5cSAndroid Build Coastguard Worker   }
139*dfc6aa5cSAndroid Build Coastguard Worker 
140*dfc6aa5cSAndroid Build Coastguard Worker   /* Give master control module another chance if this is first call to
141*dfc6aa5cSAndroid Build Coastguard Worker    * jpeg_write_raw_data.  This lets output of the frame/scan headers be
142*dfc6aa5cSAndroid Build Coastguard Worker    * delayed so that application can write COM, etc, markers between
143*dfc6aa5cSAndroid Build Coastguard Worker    * jpeg_start_compress and jpeg_write_raw_data.
144*dfc6aa5cSAndroid Build Coastguard Worker    */
145*dfc6aa5cSAndroid Build Coastguard Worker   if (cinfo->master->call_pass_startup)
146*dfc6aa5cSAndroid Build Coastguard Worker     (*cinfo->master->pass_startup) (cinfo);
147*dfc6aa5cSAndroid Build Coastguard Worker 
148*dfc6aa5cSAndroid Build Coastguard Worker   /* Verify that at least one iMCU row has been passed. */
149*dfc6aa5cSAndroid Build Coastguard Worker   lines_per_iMCU_row = cinfo->max_v_samp_factor * DCTSIZE;
150*dfc6aa5cSAndroid Build Coastguard Worker   if (num_lines < lines_per_iMCU_row)
151*dfc6aa5cSAndroid Build Coastguard Worker     ERREXIT(cinfo, JERR_BUFFER_SIZE);
152*dfc6aa5cSAndroid Build Coastguard Worker 
153*dfc6aa5cSAndroid Build Coastguard Worker   /* Directly compress the row. */
154*dfc6aa5cSAndroid Build Coastguard Worker   if (!(*cinfo->coef->compress_data) (cinfo, data)) {
155*dfc6aa5cSAndroid Build Coastguard Worker     /* If compressor did not consume the whole row, suspend processing. */
156*dfc6aa5cSAndroid Build Coastguard Worker     return 0;
157*dfc6aa5cSAndroid Build Coastguard Worker   }
158*dfc6aa5cSAndroid Build Coastguard Worker 
159*dfc6aa5cSAndroid Build Coastguard Worker   /* OK, we processed one iMCU row. */
160*dfc6aa5cSAndroid Build Coastguard Worker   cinfo->next_scanline += lines_per_iMCU_row;
161*dfc6aa5cSAndroid Build Coastguard Worker   return lines_per_iMCU_row;
162*dfc6aa5cSAndroid Build Coastguard Worker }
163