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