chromium/third_party/libjpeg_turbo/transupp.c

/*
 * transupp.c
 *
 * This file was part of the Independent JPEG Group's software:
 * Copyright (C) 1997-2019, Thomas G. Lane, Guido Vollbeding.
 * libjpeg-turbo Modifications:
 * Copyright (C) 2010, 2017, 2021-2022, D. R. Commander.
 * For conditions of distribution and use, see the accompanying README.ijg
 * file.
 *
 * This file contains image transformation routines and other utility code
 * used by the jpegtran sample application.  These are NOT part of the core
 * JPEG library.  But we keep these routines separate from jpegtran.c to
 * ease the task of maintaining jpegtran-like programs that have other user
 * interfaces.
 */

/* Although this file really shouldn't have access to the library internals,
 * it's helpful to let it call jround_up() and jcopy_block_row().
 */
#define JPEG_INTERNALS

#include "jinclude.h"
#include "jpeglib.h"
#include "transupp.h"           /* My own external interface */
#include "jpegcomp.h"
#include <ctype.h>              /* to declare isdigit() */


#if JPEG_LIB_VERSION >= 70
#define dstinfo_min_DCT_h_scaled_size
#define dstinfo_min_DCT_v_scaled_size
#else
#define dstinfo_min_DCT_h_scaled_size
#define dstinfo_min_DCT_v_scaled_size
#endif


#if TRANSFORMS_SUPPORTED

/*
 * Lossless image transformation routines.  These routines work on DCT
 * coefficient arrays and thus do not require any lossy decompression
 * or recompression of the image.
 * Thanks to Guido Vollbeding for the initial design and code of this feature,
 * and to Ben Jackson for introducing the cropping feature.
 *
 * Horizontal flipping is done in-place, using a single top-to-bottom
 * pass through the virtual source array.  It will thus be much the
 * fastest option for images larger than main memory.
 *
 * The other routines require a set of destination virtual arrays, so they
 * need twice as much memory as jpegtran normally does.  The destination
 * arrays are always written in normal scan order (top to bottom) because
 * the virtual array manager expects this.  The source arrays will be scanned
 * in the corresponding order, which means multiple passes through the source
 * arrays for most of the transforms.  That could result in much thrashing
 * if the image is larger than main memory.
 *
 * If cropping or trimming is involved, the destination arrays may be smaller
 * than the source arrays.  Note it is not possible to do horizontal flip
 * in-place when a nonzero Y crop offset is specified, since we'd have to move
 * data from one block row to another but the virtual array manager doesn't
 * guarantee we can touch more than one row at a time.  So in that case,
 * we have to use a separate destination array.
 *
 * Some notes about the operating environment of the individual transform
 * routines:
 * 1. Both the source and destination virtual arrays are allocated from the
 *    source JPEG object, and therefore should be manipulated by calling the
 *    source's memory manager.
 * 2. The destination's component count should be used.  It may be smaller
 *    than the source's when forcing to grayscale.
 * 3. Likewise the destination's sampling factors should be used.  When
 *    forcing to grayscale the destination's sampling factors will be all 1,
 *    and we may as well take that as the effective iMCU size.
 * 4. When "trim" is in effect, the destination's dimensions will be the
 *    trimmed values but the source's will be untrimmed.
 * 5. When "crop" is in effect, the destination's dimensions will be the
 *    cropped values but the source's will be uncropped.  Each transform
 *    routine is responsible for picking up source data starting at the
 *    correct X and Y offset for the crop region.  (The X and Y offsets
 *    passed to the transform routines are measured in iMCU blocks of the
 *    destination.)
 * 6. All the routines assume that the source and destination buffers are
 *    padded out to a full iMCU boundary.  This is true, although for the
 *    source buffer it is an undocumented property of jdcoefct.c.
 */


LOCAL(void)
dequant_comp(j_decompress_ptr cinfo, jpeg_component_info *compptr,
             jvirt_barray_ptr coef_array, JQUANT_TBL *qtblptr1)
{}


LOCAL(void)
requant_comp(j_decompress_ptr cinfo, jpeg_component_info *compptr,
             jvirt_barray_ptr coef_array, JQUANT_TBL *qtblptr1)
{}


/*
 * Calculate largest common denominator using Euclid's algorithm.
 */
LOCAL(JCOEF)
largest_common_denominator(JCOEF a, JCOEF b)
{}


LOCAL(void)
adjust_quant(j_decompress_ptr srcinfo, jvirt_barray_ptr *src_coef_arrays,
             j_decompress_ptr dropinfo, jvirt_barray_ptr *drop_coef_arrays,
             boolean trim, j_compress_ptr dstinfo)
{}


LOCAL(void)
do_drop(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
        JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
        jvirt_barray_ptr *src_coef_arrays,
        j_decompress_ptr dropinfo, jvirt_barray_ptr *drop_coef_arrays,
        JDIMENSION drop_width, JDIMENSION drop_height)
/* Drop (insert) the contents of another image into the source image.  If the
 * number of components in the drop image is smaller than the number of
 * components in the destination image, then we fill in the remaining
 * components with zero.  This allows for dropping the contents of grayscale
 * images into (arbitrarily sampled) color images.
 */
{}


LOCAL(void)
do_crop(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
        JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
        jvirt_barray_ptr *src_coef_arrays,
        jvirt_barray_ptr *dst_coef_arrays)
/* Crop.  This is only used when no rotate/flip is requested with the crop. */
{}


LOCAL(void)
do_crop_ext_zero(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
                 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
                 jvirt_barray_ptr *src_coef_arrays,
                 jvirt_barray_ptr *dst_coef_arrays)
/* Crop.  This is only used when no rotate/flip is requested with the crop.
 * Extension: If the destination size is larger than the source, we fill in the
 * expanded region with zero (neutral gray).  Note that we also have to zero
 * partial iMCUs at the right and bottom edge of the source image area in this
 * case.
 */
{}


LOCAL(void)
do_crop_ext_flat(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
                 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
                 jvirt_barray_ptr *src_coef_arrays,
                 jvirt_barray_ptr *dst_coef_arrays)
/* Crop.  This is only used when no rotate/flip is requested with the crop.
 * Extension: The destination width is larger than the source, and we fill in
 * the expanded region with the DC coefficient of the adjacent block.  Note
 * that we also have to fill partial iMCUs at the right and bottom edge of the
 * source image area in this case.
 */
{}


LOCAL(void)
do_crop_ext_reflect(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
                    JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
                    jvirt_barray_ptr *src_coef_arrays,
                    jvirt_barray_ptr *dst_coef_arrays)
/* Crop.  This is only used when no rotate/flip is requested with the crop.
 * Extension: The destination width is larger than the source, and we fill in
 * the expanded region with repeated reflections of the source image.  Note
 * that we also have to fill partial iMCUs at the right and bottom edge of the
 * source image area in this case.
 */
{}


LOCAL(void)
do_wipe(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
        JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
        jvirt_barray_ptr *src_coef_arrays,
        JDIMENSION drop_width, JDIMENSION drop_height)
/* Wipe - discard image contents of specified region and fill with zero
 * (neutral gray)
 */
{}


LOCAL(void)
do_flatten(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
           JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
           jvirt_barray_ptr *src_coef_arrays,
           JDIMENSION drop_width, JDIMENSION drop_height)
/* Flatten - discard image contents of specified region, similarly to wipe,
 * but fill with the average of adjacent blocks instead of zero.
 */
{}


LOCAL(void)
do_reflect(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
           JDIMENSION x_crop_offset, jvirt_barray_ptr *src_coef_arrays,
           JDIMENSION drop_width, JDIMENSION drop_height)
/* Reflect - discard image contents of specified region, similarly to wipe,
 * but fill with repeated reflections of the outside region instead of zero.
 * NB: y_crop_offset is assumed to be zero.
 */
{}


LOCAL(void)
do_flip_h_no_crop(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
                  JDIMENSION x_crop_offset, jvirt_barray_ptr *src_coef_arrays)
/* Horizontal flip; done in-place, so no separate dest array is required.
 * NB: this only works when y_crop_offset is zero.
 */
{}


LOCAL(void)
do_flip_h(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
          JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
          jvirt_barray_ptr *src_coef_arrays,
          jvirt_barray_ptr *dst_coef_arrays)
/* Horizontal flip in general cropping case */
{}


LOCAL(void)
do_flip_v(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
          JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
          jvirt_barray_ptr *src_coef_arrays,
          jvirt_barray_ptr *dst_coef_arrays)
/* Vertical flip */
{}


LOCAL(void)
do_transpose(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
             JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
             jvirt_barray_ptr *src_coef_arrays,
             jvirt_barray_ptr *dst_coef_arrays)
/* Transpose source into destination */
{}


LOCAL(void)
do_rot_90(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
          JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
          jvirt_barray_ptr *src_coef_arrays,
          jvirt_barray_ptr *dst_coef_arrays)
/* 90 degree rotation is equivalent to
 *   1. Transposing the image;
 *   2. Horizontal mirroring.
 * These two steps are merged into a single processing routine.
 */
{}


LOCAL(void)
do_rot_270(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
           JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
           jvirt_barray_ptr *src_coef_arrays,
           jvirt_barray_ptr *dst_coef_arrays)
/* 270 degree rotation is equivalent to
 *   1. Horizontal mirroring;
 *   2. Transposing the image.
 * These two steps are merged into a single processing routine.
 */
{}


LOCAL(void)
do_rot_180(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
           JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
           jvirt_barray_ptr *src_coef_arrays,
           jvirt_barray_ptr *dst_coef_arrays)
/* 180 degree rotation is equivalent to
 *   1. Vertical mirroring;
 *   2. Horizontal mirroring.
 * These two steps are merged into a single processing routine.
 */
{}


LOCAL(void)
do_transverse(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
              JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
              jvirt_barray_ptr *src_coef_arrays,
              jvirt_barray_ptr *dst_coef_arrays)
/* Transverse transpose is equivalent to
 *   1. 180 degree rotation;
 *   2. Transposition;
 * or
 *   1. Horizontal mirroring;
 *   2. Transposition;
 *   3. Horizontal mirroring.
 * These steps are merged into a single processing routine.
 */
{}


/* Parse an unsigned integer: subroutine for jtransform_parse_crop_spec.
 * Returns TRUE if valid integer found, FALSE if not.
 * *strptr is advanced over the digit string, and *result is set to its value.
 */

LOCAL(boolean)
jt_read_integer(const char **strptr, JDIMENSION *result)
{}


/* Parse a crop specification (written in X11 geometry style).
 * The routine returns TRUE if the spec string is valid, FALSE if not.
 *
 * The crop spec string should have the format
 *      <width>[{fr}]x<height>[{fr}]{+-}<xoffset>{+-}<yoffset>
 * where width, height, xoffset, and yoffset are unsigned integers.
 * Each of the elements can be omitted to indicate a default value.
 * (A weakness of this style is that it is not possible to omit xoffset
 * while specifying yoffset, since they look alike.)
 *
 * This code is loosely based on XParseGeometry from the X11 distribution.
 */

GLOBAL(boolean)
jtransform_parse_crop_spec(jpeg_transform_info *info, const char *spec)
{}


/* Trim off any partial iMCUs on the indicated destination edge */

LOCAL(void)
trim_right_edge(jpeg_transform_info *info, JDIMENSION full_width)
{}

LOCAL(void)
trim_bottom_edge(jpeg_transform_info *info, JDIMENSION full_height)
{}


/* Request any required workspace.
 *
 * This routine figures out the size that the output image will be
 * (which implies that all the transform parameters must be set before
 * it is called).
 *
 * We allocate the workspace virtual arrays from the source decompression
 * object, so that all the arrays (both the original data and the workspace)
 * will be taken into account while making memory management decisions.
 * Hence, this routine must be called after jpeg_read_header (which reads
 * the image dimensions) and before jpeg_read_coefficients (which realizes
 * the source's virtual arrays).
 *
 * This function returns FALSE right away if -perfect is given
 * and transformation is not perfect.  Otherwise returns TRUE.
 */

GLOBAL(boolean)
jtransform_request_workspace(j_decompress_ptr srcinfo,
                             jpeg_transform_info *info)
{}


/* Transpose destination image parameters */

LOCAL(void)
transpose_critical_parameters(j_compress_ptr dstinfo)
{}


/* Adjust Exif image parameters.
 *
 * We try to adjust the Tags ExifImageWidth and ExifImageHeight if possible.
 */

LOCAL(void)
adjust_exif_parameters(JOCTET *data, unsigned int length, JDIMENSION new_width,
                       JDIMENSION new_height)
{}


/* Adjust output image parameters as needed.
 *
 * This must be called after jpeg_copy_critical_parameters()
 * and before jpeg_write_coefficients().
 *
 * The return value is the set of virtual coefficient arrays to be written
 * (either the ones allocated by jtransform_request_workspace, or the
 * original source data arrays).  The caller will need to pass this value
 * to jpeg_write_coefficients().
 */

GLOBAL(jvirt_barray_ptr *)
jtransform_adjust_parameters(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
                             jvirt_barray_ptr *src_coef_arrays,
                             jpeg_transform_info *info)
{}


/* Execute the actual transformation, if any.
 *
 * This must be called *after* jpeg_write_coefficients, because it depends
 * on jpeg_write_coefficients to have computed subsidiary values such as
 * the per-component width and height fields in the destination object.
 *
 * Note that some transformations will modify the source data arrays!
 */

GLOBAL(void)
jtransform_execute_transform(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
                             jvirt_barray_ptr *src_coef_arrays,
                             jpeg_transform_info *info)
{}

/* jtransform_perfect_transform
 *
 * Determine whether lossless transformation is perfectly
 * possible for a specified image and transformation.
 *
 * Inputs:
 *   image_width, image_height: source image dimensions.
 *   MCU_width, MCU_height: pixel dimensions of MCU.
 *   transform: transformation identifier.
 * Parameter sources from initialized jpeg_struct
 * (after reading source header):
 *   image_width = cinfo.image_width
 *   image_height = cinfo.image_height
 *   MCU_width = cinfo.max_h_samp_factor * cinfo.block_size
 *   MCU_height = cinfo.max_v_samp_factor * cinfo.block_size
 * Result:
 *   TRUE = perfect transformation possible
 *   FALSE = perfect transformation not possible
 *           (may use custom action then)
 */

GLOBAL(boolean)
jtransform_perfect_transform(JDIMENSION image_width, JDIMENSION image_height,
                             int MCU_width, int MCU_height,
                             JXFORM_CODE transform)
{}

#endif /* TRANSFORMS_SUPPORTED */


/* Setup decompression object to save desired markers in memory.
 * This must be called before jpeg_read_header() to have the desired effect.
 */

GLOBAL(void)
jcopy_markers_setup(j_decompress_ptr srcinfo, JCOPY_OPTION option)
{}

/* Copy markers saved in the given source object to the destination object.
 * This should be called just after jpeg_start_compress() or
 * jpeg_write_coefficients().
 * Note that those routines will have written the SOI, and also the
 * JFIF APP0 or Adobe APP14 markers if selected.
 */

GLOBAL(void)
jcopy_markers_execute(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
                      JCOPY_OPTION option)
{}