123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131 |
- /*
- * jchuff.h
- *
- * This file was part of the Independent JPEG Group's software:
- * Copyright (C) 1991-1997, Thomas G. Lane.
- * libjpeg-turbo Modifications:
- * Copyright (C) 2009, 2018, 2021, D. R. Commander.
- * Copyright (C) 2018, Matthias Räncker.
- * Copyright (C) 2020-2021, Arm Limited.
- * For conditions of distribution and use, see the accompanying README.ijg
- * file.
- */
- /* Expanded entropy encoder object for Huffman encoding.
- *
- * The savable_state subrecord contains fields that change within an MCU,
- * but must not be updated permanently until we complete the MCU.
- */
- #if defined(__aarch64__) || defined(_M_ARM64)
- #define BIT_BUF_SIZE 64
- #else
- #define BIT_BUF_SIZE 32
- #endif
- typedef struct {
- size_t put_buffer; /* current bit accumulation buffer */
- int free_bits; /* # of bits available in it */
- int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */
- } savable_state;
- typedef struct {
- JOCTET *next_output_byte; /* => next byte to write in buffer */
- size_t free_in_buffer; /* # of byte spaces remaining in buffer */
- savable_state cur; /* Current bit buffer & DC state */
- j_compress_ptr cinfo; /* dump_buffer needs access to this */
- int simd;
- } working_state;
- /* Outputting bits to the file */
- /* Output byte b and, speculatively, an additional 0 byte. 0xFF must be encoded
- * as 0xFF 0x00, so the output buffer pointer is advanced by 2 if the byte is
- * 0xFF. Otherwise, the output buffer pointer is advanced by 1, and the
- * speculative 0 byte will be overwritten by the next byte.
- */
- #define EMIT_BYTE(b) { \
- buffer[0] = (JOCTET)(b); \
- buffer[1] = 0; \
- buffer -= -2 + ((JOCTET)(b) < 0xFF); \
- }
- /* Output the entire bit buffer. If there are no 0xFF bytes in it, then write
- * directly to the output buffer. Otherwise, use the EMIT_BYTE() macro to
- * encode 0xFF as 0xFF 0x00.
- */
- #if defined(__aarch64__) || defined(_M_ARM64)
- #define FLUSH() { \
- if (put_buffer & 0x8080808080808080 & ~(put_buffer + 0x0101010101010101)) { \
- EMIT_BYTE(put_buffer >> 56) \
- EMIT_BYTE(put_buffer >> 48) \
- EMIT_BYTE(put_buffer >> 40) \
- EMIT_BYTE(put_buffer >> 32) \
- EMIT_BYTE(put_buffer >> 24) \
- EMIT_BYTE(put_buffer >> 16) \
- EMIT_BYTE(put_buffer >> 8) \
- EMIT_BYTE(put_buffer ) \
- } else { \
- *((uint64_t *)buffer) = BUILTIN_BSWAP64(put_buffer); \
- buffer += 8; \
- } \
- }
- #else
- #if defined(_MSC_VER) && !defined(__clang__)
- #define SPLAT() { \
- buffer[0] = (JOCTET)(put_buffer >> 24); \
- buffer[1] = (JOCTET)(put_buffer >> 16); \
- buffer[2] = (JOCTET)(put_buffer >> 8); \
- buffer[3] = (JOCTET)(put_buffer ); \
- buffer += 4; \
- }
- #else
- #define SPLAT() { \
- put_buffer = __builtin_bswap32(put_buffer); \
- __asm__("str %1, [%0], #4" : "+r" (buffer) : "r" (put_buffer)); \
- }
- #endif
- #define FLUSH() { \
- if (put_buffer & 0x80808080 & ~(put_buffer + 0x01010101)) { \
- EMIT_BYTE(put_buffer >> 24) \
- EMIT_BYTE(put_buffer >> 16) \
- EMIT_BYTE(put_buffer >> 8) \
- EMIT_BYTE(put_buffer ) \
- } else { \
- SPLAT(); \
- } \
- }
- #endif
- /* Fill the bit buffer to capacity with the leading bits from code, then output
- * the bit buffer and put the remaining bits from code into the bit buffer.
- */
- #define PUT_AND_FLUSH(code, size) { \
- put_buffer = (put_buffer << (size + free_bits)) | (code >> -free_bits); \
- FLUSH() \
- free_bits += BIT_BUF_SIZE; \
- put_buffer = code; \
- }
- /* Insert code into the bit buffer and output the bit buffer if needed.
- * NOTE: We can't flush with free_bits == 0, since the left shift in
- * PUT_AND_FLUSH() would have undefined behavior.
- */
- #define PUT_BITS(code, size) { \
- free_bits -= size; \
- if (free_bits < 0) \
- PUT_AND_FLUSH(code, size) \
- else \
- put_buffer = (put_buffer << size) | code; \
- }
- #define PUT_CODE(code, size, diff) { \
- diff |= code << nbits; \
- nbits += size; \
- PUT_BITS(diff, nbits) \
- }
|