• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)
start_pass_main(j_compress_ptr cinfo,J_BUF_MODE pass_mode)53 start_pass_main(j_compress_ptr cinfo, J_BUF_MODE pass_mode)
54 {
55   my_main_ptr main_ptr = (my_main_ptr)cinfo->main;
56 
57   /* Do nothing in raw-data mode. */
58   if (cinfo->raw_data_in)
59     return;
60 
61   if (pass_mode != JBUF_PASS_THRU)
62     ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
63 
64   main_ptr->cur_iMCU_row = 0;   /* initialize counters */
65   main_ptr->rowgroup_ctr = 0;
66   main_ptr->suspended = FALSE;
67   main_ptr->pass_mode = pass_mode;      /* save mode for use by process_data */
68   main_ptr->pub.process_data = process_data_simple_main;
69 }
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)
process_data_simple_main(j_compress_ptr cinfo,JSAMPARRAY input_buf,JDIMENSION * in_row_ctr,JDIMENSION in_rows_avail)79 process_data_simple_main(j_compress_ptr cinfo, JSAMPARRAY input_buf,
80                          JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail)
81 {
82   my_main_ptr main_ptr = (my_main_ptr)cinfo->main;
83 
84   while (main_ptr->cur_iMCU_row < cinfo->total_iMCU_rows) {
85     /* Read input data if we haven't filled the main buffer yet */
86     if (main_ptr->rowgroup_ctr < DCTSIZE)
87       (*cinfo->prep->pre_process_data) (cinfo, input_buf, in_row_ctr,
88                                         in_rows_avail, main_ptr->buffer,
89                                         &main_ptr->rowgroup_ctr,
90                                         (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     if (main_ptr->rowgroup_ctr != DCTSIZE)
97       return;
98 
99     /* Send the completed row to the compressor */
100     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       if (!main_ptr->suspended) {
108         (*in_row_ctr)--;
109         main_ptr->suspended = TRUE;
110       }
111       return;
112     }
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     if (main_ptr->suspended) {
117       (*in_row_ctr)++;
118       main_ptr->suspended = FALSE;
119     }
120     main_ptr->rowgroup_ctr = 0;
121     main_ptr->cur_iMCU_row++;
122   }
123 }
124 
125 
126 /*
127  * Initialize main buffer controller.
128  */
129 
130 GLOBAL(void)
jinit_c_main_controller(j_compress_ptr cinfo,boolean need_full_buffer)131 jinit_c_main_controller(j_compress_ptr cinfo, boolean need_full_buffer)
132 {
133   my_main_ptr main_ptr;
134   int ci;
135   jpeg_component_info *compptr;
136 
137   main_ptr = (my_main_ptr)
138     (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
139                                 sizeof(my_main_controller));
140   cinfo->main = (struct jpeg_c_main_controller *)main_ptr;
141   main_ptr->pub.start_pass = start_pass_main;
142 
143   /* We don't need to create a buffer in raw-data mode. */
144   if (cinfo->raw_data_in)
145     return;
146 
147   /* Create the buffer.  It holds downsampled data, so each component
148    * may be of a different size.
149    */
150   if (need_full_buffer) {
151     ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
152   } else {
153     /* Allocate a strip buffer for each component */
154     for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
155          ci++, compptr++) {
156       main_ptr->buffer[ci] = (*cinfo->mem->alloc_sarray)
157         ((j_common_ptr)cinfo, JPOOL_IMAGE,
158          compptr->width_in_blocks * DCTSIZE,
159          (JDIMENSION)(compptr->v_samp_factor * DCTSIZE));
160     }
161   }
162 }
163