• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * jchuff.h
3  *
4  * This file was part of the Independent JPEG Group's software:
5  * Copyright (C) 1991-1997, Thomas G. Lane.
6  * libjpeg-turbo Modifications:
7  * Copyright (C) 2009, 2018, D. R. Commander.
8  * Copyright (C) 2018, Matthias Räncker.
9  * Copyright (C) 2020-2021, Arm Limited.
10  * For conditions of distribution and use, see the accompanying README.ijg
11  * file.
12  */
13 
14 /* Expanded entropy encoder object for Huffman encoding.
15  *
16  * The savable_state subrecord contains fields that change within an MCU,
17  * but must not be updated permanently until we complete the MCU.
18  */
19 
20 #if defined(__aarch64__) || defined(_M_ARM64)
21 #define BIT_BUF_SIZE  64
22 #else
23 #define BIT_BUF_SIZE  32
24 #endif
25 
26 typedef struct {
27   size_t put_buffer;                    /* current bit accumulation buffer */
28   int free_bits;                        /* # of bits available in it */
29   int last_dc_val[MAX_COMPS_IN_SCAN];   /* last DC coef for each component */
30 } savable_state;
31 
32 typedef struct {
33   JOCTET *next_output_byte;     /* => next byte to write in buffer */
34   size_t free_in_buffer;        /* # of byte spaces remaining in buffer */
35   savable_state cur;            /* Current bit buffer & DC state */
36   j_compress_ptr cinfo;         /* dump_buffer needs access to this */
37   int simd;
38 } working_state;
39 
40 /* Outputting bits to the file */
41 
42 /* Output byte b and, speculatively, an additional 0 byte. 0xFF must be encoded
43  * as 0xFF 0x00, so the output buffer pointer is advanced by 2 if the byte is
44  * 0xFF.  Otherwise, the output buffer pointer is advanced by 1, and the
45  * speculative 0 byte will be overwritten by the next byte.
46  */
47 #define EMIT_BYTE(b) { \
48   buffer[0] = (JOCTET)(b); \
49   buffer[1] = 0; \
50   buffer -= -2 + ((JOCTET)(b) < 0xFF); \
51 }
52 
53 /* Output the entire bit buffer.  If there are no 0xFF bytes in it, then write
54  * directly to the output buffer.  Otherwise, use the EMIT_BYTE() macro to
55  * encode 0xFF as 0xFF 0x00.
56  */
57 #if defined(__aarch64__) || defined(_M_ARM64)
58 
59 #define FLUSH() { \
60   if (put_buffer & 0x8080808080808080 & ~(put_buffer + 0x0101010101010101)) { \
61     EMIT_BYTE(put_buffer >> 56) \
62     EMIT_BYTE(put_buffer >> 48) \
63     EMIT_BYTE(put_buffer >> 40) \
64     EMIT_BYTE(put_buffer >> 32) \
65     EMIT_BYTE(put_buffer >> 24) \
66     EMIT_BYTE(put_buffer >> 16) \
67     EMIT_BYTE(put_buffer >>  8) \
68     EMIT_BYTE(put_buffer      ) \
69   } else { \
70     *((uint64_t *)buffer) = BUILTIN_BSWAP64(put_buffer); \
71     buffer += 8; \
72   } \
73 }
74 
75 #else
76 
77 #define FLUSH() { \
78   if (put_buffer & 0x80808080 & ~(put_buffer + 0x01010101)) { \
79     EMIT_BYTE(put_buffer >> 24) \
80     EMIT_BYTE(put_buffer >> 16) \
81     EMIT_BYTE(put_buffer >>  8) \
82     EMIT_BYTE(put_buffer      ) \
83   } else { \
84     *((uint32_t *)buffer) = BUILTIN_BSWAP32(put_buffer); \
85     buffer += 4; \
86   } \
87 }
88 
89 #endif
90 
91 /* Fill the bit buffer to capacity with the leading bits from code, then output
92  * the bit buffer and put the remaining bits from code into the bit buffer.
93  */
94 #define PUT_AND_FLUSH(code, size) { \
95   put_buffer = (put_buffer << (size + free_bits)) | (code >> -free_bits); \
96   FLUSH() \
97   free_bits += BIT_BUF_SIZE; \
98   put_buffer = code; \
99 }
100 
101 /* Insert code into the bit buffer and output the bit buffer if needed.
102  * NOTE: We can't flush with free_bits == 0, since the left shift in
103  * PUT_AND_FLUSH() would have undefined behavior.
104  */
105 #define PUT_BITS(code, size) { \
106   free_bits -= size; \
107   if (free_bits < 0) \
108     PUT_AND_FLUSH(code, size) \
109   else \
110     put_buffer = (put_buffer << size) | code; \
111 }
112 
113 #define PUT_CODE(code, size, diff) { \
114   diff |= code << nbits; \
115   nbits += size; \
116   PUT_BITS(diff, nbits) \
117 }
118