136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane/*
236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * jdpostct.c
336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane *
45033f3e19a31e8ad40c1a79700365aefe5664494DRC * This file was part of the Independent JPEG Group's software:
5489583f5165e05d37302e8eeec58104ea0109127Thomas G. Lane * Copyright (C) 1994-1996, Thomas G. Lane.
65033f3e19a31e8ad40c1a79700365aefe5664494DRC * It was modified by The libjpeg-turbo Project to include only code relevant
75033f3e19a31e8ad40c1a79700365aefe5664494DRC * to libjpeg-turbo.
836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * For conditions of distribution and use, see the accompanying README file.
936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane *
1036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * This file contains the decompression postprocessing controller.
1136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * This controller manages the upsampling, color conversion, and color
1236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * quantization/reduction steps; specifically, it controls the buffering
1336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * between upsample/color conversion and color quantization/reduction.
1436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane *
1536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * If no color quantization/reduction is required, then this module has no
1636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * work to do, and it just hands off to the upsample/color conversion code.
1736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * An integrated upsample/convert/quantize process would replace this module
1836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * entirely.
1936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane */
2036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
2136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#define JPEG_INTERNALS
2236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#include "jinclude.h"
2336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#include "jpeglib.h"
2436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
2536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
2636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane/* Private buffer controller object */
2736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
2836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lanetypedef struct {
2936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  struct jpeg_d_post_controller pub; /* public fields */
3036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
3136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  /* Color quantization source buffer: this holds output data from
3236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane   * the upsample/color conversion step to be passed to the quantizer.
3336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane   * For two-pass color quantization, we need a full-image buffer;
3436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane   * for one-pass operation, a strip buffer is sufficient.
3536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane   */
36e5eaf37440b8e337ab150c017df7c03faf846c51DRC  jvirt_sarray_ptr whole_image; /* virtual array, or NULL if one-pass */
37e5eaf37440b8e337ab150c017df7c03faf846c51DRC  JSAMPARRAY buffer;            /* strip buffer, or current strip of virtual */
38e5eaf37440b8e337ab150c017df7c03faf846c51DRC  JDIMENSION strip_height;      /* buffer size in rows */
3936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  /* for two-pass mode only: */
40e5eaf37440b8e337ab150c017df7c03faf846c51DRC  JDIMENSION starting_row;      /* row # of first row in current strip */
41e5eaf37440b8e337ab150c017df7c03faf846c51DRC  JDIMENSION next_row;          /* index of next row to fill/empty in strip */
4236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane} my_post_controller;
4336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
4436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lanetypedef my_post_controller * my_post_ptr;
4536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
4636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
4736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane/* Forward declarations */
48489583f5165e05d37302e8eeec58104ea0109127Thomas G. LaneMETHODDEF(void) post_process_1pass
49bc56b754e1a6a1db9ccadf64d6dda8a74140e1a3DRC        (j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
50bc56b754e1a6a1db9ccadf64d6dda8a74140e1a3DRC         JDIMENSION *in_row_group_ctr, JDIMENSION in_row_groups_avail,
51bc56b754e1a6a1db9ccadf64d6dda8a74140e1a3DRC         JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
52bc56b754e1a6a1db9ccadf64d6dda8a74140e1a3DRC         JDIMENSION out_rows_avail);
5336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#ifdef QUANT_2PASS_SUPPORTED
54489583f5165e05d37302e8eeec58104ea0109127Thomas G. LaneMETHODDEF(void) post_process_prepass
55bc56b754e1a6a1db9ccadf64d6dda8a74140e1a3DRC        (j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
56bc56b754e1a6a1db9ccadf64d6dda8a74140e1a3DRC         JDIMENSION *in_row_group_ctr, JDIMENSION in_row_groups_avail,
57bc56b754e1a6a1db9ccadf64d6dda8a74140e1a3DRC         JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
58bc56b754e1a6a1db9ccadf64d6dda8a74140e1a3DRC         JDIMENSION out_rows_avail);
59489583f5165e05d37302e8eeec58104ea0109127Thomas G. LaneMETHODDEF(void) post_process_2pass
60bc56b754e1a6a1db9ccadf64d6dda8a74140e1a3DRC        (j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
61bc56b754e1a6a1db9ccadf64d6dda8a74140e1a3DRC         JDIMENSION *in_row_group_ctr, JDIMENSION in_row_groups_avail,
62bc56b754e1a6a1db9ccadf64d6dda8a74140e1a3DRC         JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
63bc56b754e1a6a1db9ccadf64d6dda8a74140e1a3DRC         JDIMENSION out_rows_avail);
6436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#endif
6536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
6636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
6736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane/*
6836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * Initialize for a processing pass.
6936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane */
7036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
71489583f5165e05d37302e8eeec58104ea0109127Thomas G. LaneMETHODDEF(void)
7236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lanestart_pass_dpost (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)
7336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane{
7436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  my_post_ptr post = (my_post_ptr) cinfo->post;
7536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
7636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  switch (pass_mode) {
7736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  case JBUF_PASS_THRU:
7836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    if (cinfo->quantize_colors) {
7936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      /* Single-pass processing with color quantization. */
8036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      post->pub.post_process_data = post_process_1pass;
81bc79e0680a45d1ca330d690dae0340c8e17ab5e3Thomas G. Lane      /* We could be doing buffered-image output before starting a 2-pass
82bc79e0680a45d1ca330d690dae0340c8e17ab5e3Thomas G. Lane       * color quantization; in that case, jinit_d_post_controller did not
83bc79e0680a45d1ca330d690dae0340c8e17ab5e3Thomas G. Lane       * allocate a strip buffer.  Use the virtual-array buffer as workspace.
84bc79e0680a45d1ca330d690dae0340c8e17ab5e3Thomas G. Lane       */
85bc79e0680a45d1ca330d690dae0340c8e17ab5e3Thomas G. Lane      if (post->buffer == NULL) {
86e5eaf37440b8e337ab150c017df7c03faf846c51DRC        post->buffer = (*cinfo->mem->access_virt_sarray)
87e5eaf37440b8e337ab150c017df7c03faf846c51DRC          ((j_common_ptr) cinfo, post->whole_image,
88e5eaf37440b8e337ab150c017df7c03faf846c51DRC           (JDIMENSION) 0, post->strip_height, TRUE);
89bc79e0680a45d1ca330d690dae0340c8e17ab5e3Thomas G. Lane      }
9036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    } else {
9136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      /* For single-pass processing without color quantization,
9236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane       * I have no work to do; just call the upsampler directly.
9336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane       */
9436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      post->pub.post_process_data = cinfo->upsample->upsample;
9536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    }
9636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    break;
9736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#ifdef QUANT_2PASS_SUPPORTED
9836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  case JBUF_SAVE_AND_PASS:
9936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    /* First pass of 2-pass quantization */
10036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    if (post->whole_image == NULL)
10136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
10236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    post->pub.post_process_data = post_process_prepass;
10336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    break;
10436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  case JBUF_CRANK_DEST:
10536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    /* Second pass of 2-pass quantization */
10636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    if (post->whole_image == NULL)
10736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
10836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    post->pub.post_process_data = post_process_2pass;
10936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    break;
11036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#endif /* QUANT_2PASS_SUPPORTED */
11136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  default:
11236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
11336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    break;
11436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  }
11536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  post->starting_row = post->next_row = 0;
11636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane}
11736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
11836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
11936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane/*
12036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * Process some data in the one-pass (strip buffer) case.
12136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * This is used for color precision reduction as well as one-pass quantization.
12236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane */
12336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
124489583f5165e05d37302e8eeec58104ea0109127Thomas G. LaneMETHODDEF(void)
12536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lanepost_process_1pass (j_decompress_ptr cinfo,
126e5eaf37440b8e337ab150c017df7c03faf846c51DRC                    JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
127e5eaf37440b8e337ab150c017df7c03faf846c51DRC                    JDIMENSION in_row_groups_avail,
128e5eaf37440b8e337ab150c017df7c03faf846c51DRC                    JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
129e5eaf37440b8e337ab150c017df7c03faf846c51DRC                    JDIMENSION out_rows_avail)
13036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane{
13136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  my_post_ptr post = (my_post_ptr) cinfo->post;
13236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  JDIMENSION num_rows, max_rows;
13336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
13436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  /* Fill the buffer, but not more than what we can dump out in one go. */
13536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  /* Note we rely on the upsampler to detect bottom of image. */
13636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  max_rows = out_rows_avail - *out_row_ctr;
13736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  if (max_rows > post->strip_height)
13836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    max_rows = post->strip_height;
13936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  num_rows = 0;
14036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  (*cinfo->upsample->upsample) (cinfo,
141e5eaf37440b8e337ab150c017df7c03faf846c51DRC                input_buf, in_row_group_ctr, in_row_groups_avail,
142e5eaf37440b8e337ab150c017df7c03faf846c51DRC                post->buffer, &num_rows, max_rows);
14336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  /* Quantize and emit data. */
14436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  (*cinfo->cquantize->color_quantize) (cinfo,
145e5eaf37440b8e337ab150c017df7c03faf846c51DRC                post->buffer, output_buf + *out_row_ctr, (int) num_rows);
14636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  *out_row_ctr += num_rows;
14736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane}
14836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
14936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
15036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#ifdef QUANT_2PASS_SUPPORTED
15136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
15236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane/*
15336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * Process some data in the first pass of 2-pass quantization.
15436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane */
15536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
156489583f5165e05d37302e8eeec58104ea0109127Thomas G. LaneMETHODDEF(void)
15736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lanepost_process_prepass (j_decompress_ptr cinfo,
158e5eaf37440b8e337ab150c017df7c03faf846c51DRC                      JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
159e5eaf37440b8e337ab150c017df7c03faf846c51DRC                      JDIMENSION in_row_groups_avail,
160e5eaf37440b8e337ab150c017df7c03faf846c51DRC                      JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
161e5eaf37440b8e337ab150c017df7c03faf846c51DRC                      JDIMENSION out_rows_avail)
16236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane{
16336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  my_post_ptr post = (my_post_ptr) cinfo->post;
16436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  JDIMENSION old_next_row, num_rows;
16536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
16636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  /* Reposition virtual buffer if at start of strip. */
16736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  if (post->next_row == 0) {
16836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    post->buffer = (*cinfo->mem->access_virt_sarray)
169e5eaf37440b8e337ab150c017df7c03faf846c51DRC        ((j_common_ptr) cinfo, post->whole_image,
170e5eaf37440b8e337ab150c017df7c03faf846c51DRC         post->starting_row, post->strip_height, TRUE);
17136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  }
17236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
17336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  /* Upsample some data (up to a strip height's worth). */
17436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  old_next_row = post->next_row;
17536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  (*cinfo->upsample->upsample) (cinfo,
176e5eaf37440b8e337ab150c017df7c03faf846c51DRC                input_buf, in_row_group_ctr, in_row_groups_avail,
177e5eaf37440b8e337ab150c017df7c03faf846c51DRC                post->buffer, &post->next_row, post->strip_height);
17836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
17936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  /* Allow quantizer to scan new data.  No data is emitted, */
18036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  /* but we advance out_row_ctr so outer loop can tell when we're done. */
18136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  if (post->next_row > old_next_row) {
18236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    num_rows = post->next_row - old_next_row;
18336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    (*cinfo->cquantize->color_quantize) (cinfo, post->buffer + old_next_row,
184e5eaf37440b8e337ab150c017df7c03faf846c51DRC                                         (JSAMPARRAY) NULL, (int) num_rows);
18536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    *out_row_ctr += num_rows;
18636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  }
18736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
18836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  /* Advance if we filled the strip. */
18936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  if (post->next_row >= post->strip_height) {
19036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    post->starting_row += post->strip_height;
19136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    post->next_row = 0;
19236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  }
19336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane}
19436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
19536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
19636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane/*
19736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * Process some data in the second pass of 2-pass quantization.
19836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane */
19936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
200489583f5165e05d37302e8eeec58104ea0109127Thomas G. LaneMETHODDEF(void)
20136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lanepost_process_2pass (j_decompress_ptr cinfo,
202e5eaf37440b8e337ab150c017df7c03faf846c51DRC                    JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
203e5eaf37440b8e337ab150c017df7c03faf846c51DRC                    JDIMENSION in_row_groups_avail,
204e5eaf37440b8e337ab150c017df7c03faf846c51DRC                    JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
205e5eaf37440b8e337ab150c017df7c03faf846c51DRC                    JDIMENSION out_rows_avail)
20636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane{
20736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  my_post_ptr post = (my_post_ptr) cinfo->post;
20836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  JDIMENSION num_rows, max_rows;
20936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
21036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  /* Reposition virtual buffer if at start of strip. */
21136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  if (post->next_row == 0) {
21236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    post->buffer = (*cinfo->mem->access_virt_sarray)
213e5eaf37440b8e337ab150c017df7c03faf846c51DRC        ((j_common_ptr) cinfo, post->whole_image,
214e5eaf37440b8e337ab150c017df7c03faf846c51DRC         post->starting_row, post->strip_height, FALSE);
21536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  }
21636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
21736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  /* Determine number of rows to emit. */
21836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  num_rows = post->strip_height - post->next_row; /* available in strip */
21936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  max_rows = out_rows_avail - *out_row_ctr; /* available in output area */
22036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  if (num_rows > max_rows)
22136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    num_rows = max_rows;
22236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  /* We have to check bottom of image here, can't depend on upsampler. */
22336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  max_rows = cinfo->output_height - post->starting_row;
22436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  if (num_rows > max_rows)
22536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    num_rows = max_rows;
22636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
22736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  /* Quantize and emit data. */
22836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  (*cinfo->cquantize->color_quantize) (cinfo,
229e5eaf37440b8e337ab150c017df7c03faf846c51DRC                post->buffer + post->next_row, output_buf + *out_row_ctr,
230e5eaf37440b8e337ab150c017df7c03faf846c51DRC                (int) num_rows);
23136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  *out_row_ctr += num_rows;
23236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
23336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  /* Advance if we filled the strip. */
23436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  post->next_row += num_rows;
23536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  if (post->next_row >= post->strip_height) {
23636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    post->starting_row += post->strip_height;
23736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    post->next_row = 0;
23836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  }
23936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane}
24036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
24136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#endif /* QUANT_2PASS_SUPPORTED */
24236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
24336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
24436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane/*
24536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * Initialize postprocessing controller.
24636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane */
24736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
248489583f5165e05d37302e8eeec58104ea0109127Thomas G. LaneGLOBAL(void)
24936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lanejinit_d_post_controller (j_decompress_ptr cinfo, boolean need_full_buffer)
25036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane{
25136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  my_post_ptr post;
25236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
25336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  post = (my_post_ptr)
25436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
2555de454b291f48382648a5d1dc2aa0fca8b5786d4DRC                                sizeof(my_post_controller));
25636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  cinfo->post = (struct jpeg_d_post_controller *) post;
25736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  post->pub.start_pass = start_pass_dpost;
258e5eaf37440b8e337ab150c017df7c03faf846c51DRC  post->whole_image = NULL;     /* flag for no virtual arrays */
259e5eaf37440b8e337ab150c017df7c03faf846c51DRC  post->buffer = NULL;          /* flag for no strip buffer */
26036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
26136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  /* Create the quantization buffer, if needed */
26236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  if (cinfo->quantize_colors) {
26336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    /* The buffer strip height is max_v_samp_factor, which is typically
26436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane     * an efficient number of rows for upsampling to return.
26536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane     * (In the presence of output rescaling, we might want to be smarter?)
26636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane     */
26736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    post->strip_height = (JDIMENSION) cinfo->max_v_samp_factor;
26836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    if (need_full_buffer) {
26936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      /* Two-pass color quantization: need full-image storage. */
270bc79e0680a45d1ca330d690dae0340c8e17ab5e3Thomas G. Lane      /* We round up the number of rows to a multiple of the strip height. */
27136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#ifdef QUANT_2PASS_SUPPORTED
27236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      post->whole_image = (*cinfo->mem->request_virt_sarray)
273e5eaf37440b8e337ab150c017df7c03faf846c51DRC        ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
274e5eaf37440b8e337ab150c017df7c03faf846c51DRC         cinfo->output_width * cinfo->out_color_components,
275e5eaf37440b8e337ab150c017df7c03faf846c51DRC         (JDIMENSION) jround_up((long) cinfo->output_height,
276e5eaf37440b8e337ab150c017df7c03faf846c51DRC                                (long) post->strip_height),
277e5eaf37440b8e337ab150c017df7c03faf846c51DRC         post->strip_height);
27836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#else
27936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
28036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#endif /* QUANT_2PASS_SUPPORTED */
28136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    } else {
28236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      /* One-pass color quantization: just make a strip buffer. */
28336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      post->buffer = (*cinfo->mem->alloc_sarray)
284e5eaf37440b8e337ab150c017df7c03faf846c51DRC        ((j_common_ptr) cinfo, JPOOL_IMAGE,
285e5eaf37440b8e337ab150c017df7c03faf846c51DRC         cinfo->output_width * cinfo->out_color_components,
286e5eaf37440b8e337ab150c017df7c03faf846c51DRC         post->strip_height);
28736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    }
28836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  }
28936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane}
290