Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/external/source/vncdll/winvnc/libjpeg/jcprepct.c
Views: 11784
/*1* jcprepct.c2*3* Copyright (C) 1994-1996, Thomas G. Lane.4* This file is part of the Independent JPEG Group's software.5* For conditions of distribution and use, see the accompanying README file.6*7* This file contains the compression preprocessing controller.8* This controller manages the color conversion, downsampling,9* and edge expansion steps.10*11* Most of the complexity here is associated with buffering input rows12* as required by the downsampler. See the comments at the head of13* jcsample.c for the downsampler's needs.14*/1516#define JPEG_INTERNALS17#include "jinclude.h"18#include "jpeglib.h"192021/* At present, jcsample.c can request context rows only for smoothing.22* In the future, we might also need context rows for CCIR601 sampling23* or other more-complex downsampling procedures. The code to support24* context rows should be compiled only if needed.25*/26#ifdef INPUT_SMOOTHING_SUPPORTED27#define CONTEXT_ROWS_SUPPORTED28#endif293031/*32* For the simple (no-context-row) case, we just need to buffer one33* row group's worth of pixels for the downsampling step. At the bottom of34* the image, we pad to a full row group by replicating the last pixel row.35* The downsampler's last output row is then replicated if needed to pad36* out to a full iMCU row.37*38* When providing context rows, we must buffer three row groups' worth of39* pixels. Three row groups are physically allocated, but the row pointer40* arrays are made five row groups high, with the extra pointers above and41* below "wrapping around" to point to the last and first real row groups.42* This allows the downsampler to access the proper context rows.43* At the top and bottom of the image, we create dummy context rows by44* copying the first or last real pixel row. This copying could be avoided45* by pointer hacking as is done in jdmainct.c, but it doesn't seem worth the46* trouble on the compression side.47*/484950/* Private buffer controller object */5152typedef struct {53struct jpeg_c_prep_controller pub; /* public fields */5455/* Downsampling input buffer. This buffer holds color-converted data56* until we have enough to do a downsample step.57*/58JSAMPARRAY color_buf[MAX_COMPONENTS];5960JDIMENSION rows_to_go; /* counts rows remaining in source image */61int next_buf_row; /* index of next row to store in color_buf */6263#ifdef CONTEXT_ROWS_SUPPORTED /* only needed for context case */64int this_row_group; /* starting row index of group to process */65int next_buf_stop; /* downsample when we reach this index */66#endif67} my_prep_controller;6869typedef my_prep_controller * my_prep_ptr;707172/*73* Initialize for a processing pass.74*/7576METHODDEF(void)77start_pass_prep (j_compress_ptr cinfo, J_BUF_MODE pass_mode)78{79my_prep_ptr prep = (my_prep_ptr) cinfo->prep;8081if (pass_mode != JBUF_PASS_THRU)82ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);8384/* Initialize total-height counter for detecting bottom of image */85prep->rows_to_go = cinfo->image_height;86/* Mark the conversion buffer empty */87prep->next_buf_row = 0;88#ifdef CONTEXT_ROWS_SUPPORTED89/* Preset additional state variables for context mode.90* These aren't used in non-context mode, so we needn't test which mode.91*/92prep->this_row_group = 0;93/* Set next_buf_stop to stop after two row groups have been read in. */94prep->next_buf_stop = 2 * cinfo->max_v_samp_factor;95#endif96}979899/*100* Expand an image vertically from height input_rows to height output_rows,101* by duplicating the bottom row.102*/103104LOCAL(void)105expand_bottom_edge (JSAMPARRAY image_data, JDIMENSION num_cols,106int input_rows, int output_rows)107{108register int row;109110for (row = input_rows; row < output_rows; row++) {111jcopy_sample_rows(image_data, input_rows-1, image_data, row,1121, num_cols);113}114}115116117/*118* Process some data in the simple no-context case.119*120* Preprocessor output data is counted in "row groups". A row group121* is defined to be v_samp_factor sample rows of each component.122* Downsampling will produce this much data from each max_v_samp_factor123* input rows.124*/125126METHODDEF(void)127pre_process_data (j_compress_ptr cinfo,128JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,129JDIMENSION in_rows_avail,130JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr,131JDIMENSION out_row_groups_avail)132{133my_prep_ptr prep = (my_prep_ptr) cinfo->prep;134int numrows, ci;135JDIMENSION inrows;136jpeg_component_info * compptr;137138while (*in_row_ctr < in_rows_avail &&139*out_row_group_ctr < out_row_groups_avail) {140/* Do color conversion to fill the conversion buffer. */141inrows = in_rows_avail - *in_row_ctr;142numrows = cinfo->max_v_samp_factor - prep->next_buf_row;143numrows = (int) MIN((JDIMENSION) numrows, inrows);144(*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr,145prep->color_buf,146(JDIMENSION) prep->next_buf_row,147numrows);148*in_row_ctr += numrows;149prep->next_buf_row += numrows;150prep->rows_to_go -= numrows;151/* If at bottom of image, pad to fill the conversion buffer. */152if (prep->rows_to_go == 0 &&153prep->next_buf_row < cinfo->max_v_samp_factor) {154for (ci = 0; ci < cinfo->num_components; ci++) {155expand_bottom_edge(prep->color_buf[ci], cinfo->image_width,156prep->next_buf_row, cinfo->max_v_samp_factor);157}158prep->next_buf_row = cinfo->max_v_samp_factor;159}160/* If we've filled the conversion buffer, empty it. */161if (prep->next_buf_row == cinfo->max_v_samp_factor) {162(*cinfo->downsample->downsample) (cinfo,163prep->color_buf, (JDIMENSION) 0,164output_buf, *out_row_group_ctr);165prep->next_buf_row = 0;166(*out_row_group_ctr)++;167}168/* If at bottom of image, pad the output to a full iMCU height.169* Note we assume the caller is providing a one-iMCU-height output buffer!170*/171if (prep->rows_to_go == 0 &&172*out_row_group_ctr < out_row_groups_avail) {173for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;174ci++, compptr++) {175expand_bottom_edge(output_buf[ci],176compptr->width_in_blocks * DCTSIZE,177(int) (*out_row_group_ctr * compptr->v_samp_factor),178(int) (out_row_groups_avail * compptr->v_samp_factor));179}180*out_row_group_ctr = out_row_groups_avail;181break; /* can exit outer loop without test */182}183}184}185186187#ifdef CONTEXT_ROWS_SUPPORTED188189/*190* Process some data in the context case.191*/192193METHODDEF(void)194pre_process_context (j_compress_ptr cinfo,195JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,196JDIMENSION in_rows_avail,197JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr,198JDIMENSION out_row_groups_avail)199{200my_prep_ptr prep = (my_prep_ptr) cinfo->prep;201int numrows, ci;202int buf_height = cinfo->max_v_samp_factor * 3;203JDIMENSION inrows;204205while (*out_row_group_ctr < out_row_groups_avail) {206if (*in_row_ctr < in_rows_avail) {207/* Do color conversion to fill the conversion buffer. */208inrows = in_rows_avail - *in_row_ctr;209numrows = prep->next_buf_stop - prep->next_buf_row;210numrows = (int) MIN((JDIMENSION) numrows, inrows);211(*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr,212prep->color_buf,213(JDIMENSION) prep->next_buf_row,214numrows);215/* Pad at top of image, if first time through */216if (prep->rows_to_go == cinfo->image_height) {217for (ci = 0; ci < cinfo->num_components; ci++) {218int row;219for (row = 1; row <= cinfo->max_v_samp_factor; row++) {220jcopy_sample_rows(prep->color_buf[ci], 0,221prep->color_buf[ci], -row,2221, cinfo->image_width);223}224}225}226*in_row_ctr += numrows;227prep->next_buf_row += numrows;228prep->rows_to_go -= numrows;229} else {230/* Return for more data, unless we are at the bottom of the image. */231if (prep->rows_to_go != 0)232break;233/* When at bottom of image, pad to fill the conversion buffer. */234if (prep->next_buf_row < prep->next_buf_stop) {235for (ci = 0; ci < cinfo->num_components; ci++) {236expand_bottom_edge(prep->color_buf[ci], cinfo->image_width,237prep->next_buf_row, prep->next_buf_stop);238}239prep->next_buf_row = prep->next_buf_stop;240}241}242/* If we've gotten enough data, downsample a row group. */243if (prep->next_buf_row == prep->next_buf_stop) {244(*cinfo->downsample->downsample) (cinfo,245prep->color_buf,246(JDIMENSION) prep->this_row_group,247output_buf, *out_row_group_ctr);248(*out_row_group_ctr)++;249/* Advance pointers with wraparound as necessary. */250prep->this_row_group += cinfo->max_v_samp_factor;251if (prep->this_row_group >= buf_height)252prep->this_row_group = 0;253if (prep->next_buf_row >= buf_height)254prep->next_buf_row = 0;255prep->next_buf_stop = prep->next_buf_row + cinfo->max_v_samp_factor;256}257}258}259260261/*262* Create the wrapped-around downsampling input buffer needed for context mode.263*/264265LOCAL(void)266create_context_buffer (j_compress_ptr cinfo)267{268my_prep_ptr prep = (my_prep_ptr) cinfo->prep;269int rgroup_height = cinfo->max_v_samp_factor;270int ci, i;271jpeg_component_info * compptr;272JSAMPARRAY true_buffer, fake_buffer;273274/* Grab enough space for fake row pointers for all the components;275* we need five row groups' worth of pointers for each component.276*/277fake_buffer = (JSAMPARRAY)278(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,279(cinfo->num_components * 5 * rgroup_height) *280SIZEOF(JSAMPROW));281282for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;283ci++, compptr++) {284/* Allocate the actual buffer space (3 row groups) for this component.285* We make the buffer wide enough to allow the downsampler to edge-expand286* horizontally within the buffer, if it so chooses.287*/288true_buffer = (*cinfo->mem->alloc_sarray)289((j_common_ptr) cinfo, JPOOL_IMAGE,290(JDIMENSION) (((long) compptr->width_in_blocks * DCTSIZE *291cinfo->max_h_samp_factor) / compptr->h_samp_factor),292(JDIMENSION) (3 * rgroup_height));293/* Copy true buffer row pointers into the middle of the fake row array */294MEMCOPY(fake_buffer + rgroup_height, true_buffer,2953 * rgroup_height * SIZEOF(JSAMPROW));296/* Fill in the above and below wraparound pointers */297for (i = 0; i < rgroup_height; i++) {298fake_buffer[i] = true_buffer[2 * rgroup_height + i];299fake_buffer[4 * rgroup_height + i] = true_buffer[i];300}301prep->color_buf[ci] = fake_buffer + rgroup_height;302fake_buffer += 5 * rgroup_height; /* point to space for next component */303}304}305306#endif /* CONTEXT_ROWS_SUPPORTED */307308309/*310* Initialize preprocessing controller.311*/312313GLOBAL(void)314jinit_c_prep_controller (j_compress_ptr cinfo, boolean need_full_buffer)315{316my_prep_ptr prep;317int ci;318jpeg_component_info * compptr;319320if (need_full_buffer) /* safety check */321ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);322323prep = (my_prep_ptr)324(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,325SIZEOF(my_prep_controller));326cinfo->prep = (struct jpeg_c_prep_controller *) prep;327prep->pub.start_pass = start_pass_prep;328329/* Allocate the color conversion buffer.330* We make the buffer wide enough to allow the downsampler to edge-expand331* horizontally within the buffer, if it so chooses.332*/333if (cinfo->downsample->need_context_rows) {334/* Set up to provide context rows */335#ifdef CONTEXT_ROWS_SUPPORTED336prep->pub.pre_process_data = pre_process_context;337create_context_buffer(cinfo);338#else339ERREXIT(cinfo, JERR_NOT_COMPILED);340#endif341} else {342/* No context, just make it tall enough for one row group */343prep->pub.pre_process_data = pre_process_data;344for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;345ci++, compptr++) {346prep->color_buf[ci] = (*cinfo->mem->alloc_sarray)347((j_common_ptr) cinfo, JPOOL_IMAGE,348(JDIMENSION) (((long) compptr->width_in_blocks * DCTSIZE *349cinfo->max_h_samp_factor) / compptr->h_samp_factor),350(JDIMENSION) cinfo->max_v_samp_factor);351}352}353}354355356