libjxl

FORK: libjxl patches used on blog
git clone https://git.neptards.moe/blog/libjxl.git
Log | Files | Refs | Submodules | README | LICENSE

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_