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