bit_writer.h (3139B)
1 // Copyright (c) the JPEG XL Project Authors. All rights reserved. 2 // 3 // Use of this source code is governed by a BSD-style 4 // license that can be found in the LICENSE file. 5 6 #ifndef LIB_JPEGLI_BIT_WRITER_H_ 7 #define LIB_JPEGLI_BIT_WRITER_H_ 8 9 #include <stdint.h> 10 #include <string.h> 11 12 #include "lib/jpegli/common.h" 13 #include "lib/jxl/base/byte_order.h" 14 #include "lib/jxl/base/compiler_specific.h" 15 16 namespace jpegli { 17 18 // Handles the packing of bits into output bytes. 19 struct JpegBitWriter { 20 j_compress_ptr cinfo; 21 uint8_t* data; 22 size_t len; 23 size_t pos; 24 size_t output_pos; 25 uint64_t put_buffer; 26 int free_bits; 27 bool healthy; 28 }; 29 30 void JpegBitWriterInit(j_compress_ptr cinfo); 31 32 bool EmptyBitWriterBuffer(JpegBitWriter* bw); 33 34 void JumpToByteBoundary(JpegBitWriter* bw); 35 36 // Returns non-zero if and only if x has a zero byte, i.e. one of 37 // x & 0xff, x & 0xff00, ..., x & 0xff00000000000000 is zero. 38 static JXL_INLINE uint64_t HasZeroByte(uint64_t x) { 39 return (x - 0x0101010101010101ULL) & ~x & 0x8080808080808080ULL; 40 } 41 42 /** 43 * Writes the given byte to the output, writes an extra zero if byte is 0xFF. 44 * 45 * This method is "careless" - caller must make sure that there is enough 46 * space in the output buffer. Emits up to 2 bytes to buffer. 47 */ 48 static JXL_INLINE void EmitByte(JpegBitWriter* bw, int byte) { 49 bw->data[bw->pos++] = byte; 50 if (byte == 0xFF) bw->data[bw->pos++] = 0; 51 } 52 53 static JXL_INLINE void DischargeBitBuffer(JpegBitWriter* bw) { 54 // At this point we are ready to emit the bytes of put_buffer to the output. 55 // The JPEG format requires that after every 0xff byte in the entropy 56 // coded section, there is a zero byte, therefore we first check if any of 57 // the bytes of put_buffer is 0xFF. 58 if (HasZeroByte(~bw->put_buffer)) { 59 // We have a 0xFF byte somewhere, examine each byte and append a zero 60 // byte if necessary. 61 EmitByte(bw, (bw->put_buffer >> 56) & 0xFF); 62 EmitByte(bw, (bw->put_buffer >> 48) & 0xFF); 63 EmitByte(bw, (bw->put_buffer >> 40) & 0xFF); 64 EmitByte(bw, (bw->put_buffer >> 32) & 0xFF); 65 EmitByte(bw, (bw->put_buffer >> 24) & 0xFF); 66 EmitByte(bw, (bw->put_buffer >> 16) & 0xFF); 67 EmitByte(bw, (bw->put_buffer >> 8) & 0xFF); 68 EmitByte(bw, (bw->put_buffer >> 0) & 0xFF); 69 } else { 70 // We don't have any 0xFF bytes, output all 8 bytes without checking. 71 StoreBE64(bw->put_buffer, bw->data + bw->pos); 72 bw->pos += 8; 73 } 74 } 75 76 static JXL_INLINE void WriteBits(JpegBitWriter* bw, int nbits, uint64_t bits) { 77 // This is an optimization; if everything goes well, 78 // then |nbits| is positive; if non-existing Huffman symbol is going to be 79 // encoded, its length should be zero; later encoder could check the 80 // "health" of JpegBitWriter. 81 if (nbits == 0) { 82 bw->healthy = false; 83 return; 84 } 85 bw->free_bits -= nbits; 86 if (bw->free_bits < 0) { 87 bw->put_buffer <<= (bw->free_bits + nbits); 88 bw->put_buffer |= (bits >> -bw->free_bits); 89 DischargeBitBuffer(bw); 90 bw->free_bits += 64; 91 bw->put_buffer = nbits; 92 } 93 bw->put_buffer <<= nbits; 94 bw->put_buffer |= bits; 95 } 96 97 } // namespace jpegli 98 #endif // LIB_JPEGLI_BIT_WRITER_H_