/* * jcphuff.c * * This file was part of the Independent JPEG Group's software: * Copyright (C) 1995-1997, Thomas G. Lane. * libjpeg-turbo Modifications: * Copyright (C) 2011, 2015, 2018, 2021-2022, D. R. Commander. * Copyright (C) 2016, 2018, 2022, Matthieu Darbois. * Copyright (C) 2020, Arm Limited. * Copyright (C) 2021, Alex Richardson. * For conditions of distribution and use, see the accompanying README.ijg * file. * * This file contains Huffman entropy encoding routines for progressive JPEG. * * We do not support output suspension in this module, since the library * currently does not allow multiple-scan files to be written with output * suspension. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" #include "jsimd.h" #include <limits.h> #ifdef HAVE_INTRIN_H #include <intrin.h> #ifdef _MSC_VER #ifdef HAVE_BITSCANFORWARD64 #pragma intrinsic(_BitScanForward64) #endif #ifdef HAVE_BITSCANFORWARD #pragma intrinsic(_BitScanForward) #endif #endif #endif #ifdef C_PROGRESSIVE_SUPPORTED /* * NOTE: If USE_CLZ_INTRINSIC is defined, then clz/bsr instructions will be * used for bit counting rather than the lookup table. This will reduce the * memory footprint by 64k, which is important for some mobile applications * that create many isolated instances of libjpeg-turbo (web browsers, for * instance.) This may improve performance on some mobile platforms as well. * This feature is enabled by default only on Arm processors, because some x86 * chips have a slow implementation of bsr, and the use of clz/bsr cannot be * shown to have a significant performance impact even on the x86 chips that * have a fast implementation of it. When building for Armv6, you can * explicitly disable the use of clz/bsr by adding -mthumb to the compiler * flags (this defines __thumb__). */ /* NOTE: Both GCC and Clang define __GNUC__ */ #if (defined(__GNUC__) && (defined(__arm__) || defined(__aarch64__))) || \ defined(_M_ARM) || defined(_M_ARM64) #if !defined(__thumb__) || defined(__thumb2__) #define USE_CLZ_INTRINSIC #endif #endif #ifdef USE_CLZ_INTRINSIC #if defined(_MSC_VER) && !defined(__clang__) #define JPEG_NBITS_NONZERO … #else #define JPEG_NBITS_NONZERO … #endif #define JPEG_NBITS … #else #include "jpeg_nbits_table.h" #define JPEG_NBITS(x) … #define JPEG_NBITS_NONZERO(x) … #endif /* Expanded entropy encoder object for progressive Huffman encoding. */ phuff_entropy_encoder; phuff_entropy_ptr; /* MAX_CORR_BITS is the number of bits the AC refinement correction-bit * buffer can hold. Larger sizes may slightly improve compression, but * 1000 is already well into the realm of overkill. * The minimum safe size is 64 bits. */ #define MAX_CORR_BITS … /* IRIGHT_SHIFT is like RIGHT_SHIFT, but works on int rather than JLONG. * We assume that int right shift is unsigned if JLONG right shift is, * which should be safe. */ #ifdef RIGHT_SHIFT_IS_UNSIGNED #define ISHIFT_TEMPS … #define IRIGHT_SHIFT … #else #define ISHIFT_TEMPS #define IRIGHT_SHIFT(x, shft) … #endif #define PAD(v, p) … /* Forward declarations */ METHODDEF(boolean) encode_mcu_DC_first(j_compress_ptr cinfo, JBLOCKROW *MCU_data); METHODDEF(void) encode_mcu_AC_first_prepare (const JCOEF *block, const int *jpeg_natural_order_start, int Sl, int Al, UJCOEF *values, size_t *zerobits); METHODDEF(boolean) encode_mcu_AC_first(j_compress_ptr cinfo, JBLOCKROW *MCU_data); METHODDEF(boolean) encode_mcu_DC_refine(j_compress_ptr cinfo, JBLOCKROW *MCU_data); METHODDEF(int) encode_mcu_AC_refine_prepare (const JCOEF *block, const int *jpeg_natural_order_start, int Sl, int Al, UJCOEF *absvalues, size_t *bits); METHODDEF(boolean) encode_mcu_AC_refine(j_compress_ptr cinfo, JBLOCKROW *MCU_data); METHODDEF(void) finish_pass_phuff(j_compress_ptr cinfo); METHODDEF(void) finish_pass_gather_phuff(j_compress_ptr cinfo); /* Count bit loop zeroes */ INLINE METHODDEF(int) count_zeroes(size_t *x) { … } /* * Initialize for a Huffman-compressed scan using progressive JPEG. */ METHODDEF(void) start_pass_phuff(j_compress_ptr cinfo, boolean gather_statistics) { … } /* Outputting bytes to the file. * NB: these must be called only when actually outputting, * that is, entropy->gather_statistics == FALSE. */ /* Emit a byte */ #define emit_byte(entropy, val) … LOCAL(void) dump_buffer(phuff_entropy_ptr entropy) /* Empty the output buffer; we do not support suspension in this module. */ { … } /* Outputting bits to the file */ /* Only the right 24 bits of put_buffer are used; the valid bits are * left-justified in this part. At most 16 bits can be passed to emit_bits * in one call, and we never retain more than 7 bits in put_buffer * between calls, so 24 bits are sufficient. */ LOCAL(void) emit_bits(phuff_entropy_ptr entropy, unsigned int code, int size) /* Emit some bits, unless we are in gather mode */ { … } LOCAL(void) flush_bits(phuff_entropy_ptr entropy) { … } /* * Emit (or just count) a Huffman symbol. */ LOCAL(void) emit_symbol(phuff_entropy_ptr entropy, int tbl_no, int symbol) { … } /* * Emit bits from a correction bit buffer. */ LOCAL(void) emit_buffered_bits(phuff_entropy_ptr entropy, char *bufstart, unsigned int nbits) { … } /* * Emit any pending EOBRUN symbol. */ LOCAL(void) emit_eobrun(phuff_entropy_ptr entropy) { … } /* * Emit a restart marker & resynchronize predictions. */ LOCAL(void) emit_restart(phuff_entropy_ptr entropy, int restart_num) { … } /* * MCU encoding for DC initial scan (either spectral selection, * or first pass of successive approximation). */ METHODDEF(boolean) encode_mcu_DC_first(j_compress_ptr cinfo, JBLOCKROW *MCU_data) { … } /* * Data preparation for encode_mcu_AC_first(). */ #define COMPUTE_ABSVALUES_AC_FIRST(Sl) … METHODDEF(void) encode_mcu_AC_first_prepare(const JCOEF *block, const int *jpeg_natural_order_start, int Sl, int Al, UJCOEF *values, size_t *bits) { … } /* * MCU encoding for AC initial scan (either spectral selection, * or first pass of successive approximation). */ #define ENCODE_COEFS_AC_FIRST(label) … METHODDEF(boolean) encode_mcu_AC_first(j_compress_ptr cinfo, JBLOCKROW *MCU_data) { … } /* * MCU encoding for DC successive approximation refinement scan. * Note: we assume such scans can be multi-component, although the spec * is not very clear on the point. */ METHODDEF(boolean) encode_mcu_DC_refine(j_compress_ptr cinfo, JBLOCKROW *MCU_data) { … } /* * Data preparation for encode_mcu_AC_refine(). */ #define COMPUTE_ABSVALUES_AC_REFINE(Sl, koffset) … METHODDEF(int) encode_mcu_AC_refine_prepare(const JCOEF *block, const int *jpeg_natural_order_start, int Sl, int Al, UJCOEF *absvalues, size_t *bits) { … } /* * MCU encoding for AC successive approximation refinement scan. */ #define ENCODE_COEFS_AC_REFINE(label) … METHODDEF(boolean) encode_mcu_AC_refine(j_compress_ptr cinfo, JBLOCKROW *MCU_data) { … } /* * Finish up at the end of a Huffman-compressed progressive scan. */ METHODDEF(void) finish_pass_phuff(j_compress_ptr cinfo) { … } /* * Finish up a statistics-gathering pass and create the new Huffman tables. */ METHODDEF(void) finish_pass_gather_phuff(j_compress_ptr cinfo) { … } /* * Module initialization routine for progressive Huffman entropy encoding. */ GLOBAL(void) jinit_phuff_encoder(j_compress_ptr cinfo) { … } #endif /* C_PROGRESSIVE_SUPPORTED */