Coverage Report

Created: 2024-09-08 07:14

/src/libjxl/lib/jpegli/bit_writer.h
Line
Count
Source (jump to first uncovered line)
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
0
static JXL_INLINE uint64_t HasZeroByte(uint64_t x) {
39
0
  return (x - 0x0101010101010101ULL) & ~x & 0x8080808080808080ULL;
40
0
}
Unexecuted instantiation: common.cc:jpegli::HasZeroByte(unsigned long)
Unexecuted instantiation: color_transform.cc:jpegli::HasZeroByte(unsigned long)
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
0
static JXL_INLINE void EmitByte(JpegBitWriter* bw, int byte) {
49
0
  bw->data[bw->pos++] = byte;
50
0
  if (byte == 0xFF) bw->data[bw->pos++] = 0;
51
0
}
Unexecuted instantiation: common.cc:jpegli::EmitByte(jpegli::JpegBitWriter*, int)
Unexecuted instantiation: color_transform.cc:jpegli::EmitByte(jpegli::JpegBitWriter*, int)
52
53
0
static JXL_INLINE void DischargeBitBuffer(JpegBitWriter* bw) {
54
0
  // At this point we are ready to emit the bytes of put_buffer to the output.
55
0
  // The JPEG format requires that after every 0xff byte in the entropy
56
0
  // coded section, there is a zero byte, therefore we first check if any of
57
0
  // the bytes of put_buffer is 0xFF.
58
0
  if (HasZeroByte(~bw->put_buffer)) {
59
0
    // We have a 0xFF byte somewhere, examine each byte and append a zero
60
0
    // byte if necessary.
61
0
    EmitByte(bw, (bw->put_buffer >> 56) & 0xFF);
62
0
    EmitByte(bw, (bw->put_buffer >> 48) & 0xFF);
63
0
    EmitByte(bw, (bw->put_buffer >> 40) & 0xFF);
64
0
    EmitByte(bw, (bw->put_buffer >> 32) & 0xFF);
65
0
    EmitByte(bw, (bw->put_buffer >> 24) & 0xFF);
66
0
    EmitByte(bw, (bw->put_buffer >> 16) & 0xFF);
67
0
    EmitByte(bw, (bw->put_buffer >> 8) & 0xFF);
68
0
    EmitByte(bw, (bw->put_buffer >> 0) & 0xFF);
69
0
  } else {
70
0
    // We don't have any 0xFF bytes, output all 8 bytes without checking.
71
0
    StoreBE64(bw->put_buffer, bw->data + bw->pos);
72
0
    bw->pos += 8;
73
0
  }
74
0
}
Unexecuted instantiation: common.cc:jpegli::DischargeBitBuffer(jpegli::JpegBitWriter*)
Unexecuted instantiation: color_transform.cc:jpegli::DischargeBitBuffer(jpegli::JpegBitWriter*)
75
76
0
static JXL_INLINE void WriteBits(JpegBitWriter* bw, int nbits, uint64_t bits) {
77
0
  // This is an optimization; if everything goes well,
78
0
  // then |nbits| is positive; if non-existing Huffman symbol is going to be
79
0
  // encoded, its length should be zero; later encoder could check the
80
0
  // "health" of JpegBitWriter.
81
0
  if (nbits == 0) {
82
0
    bw->healthy = false;
83
0
    return;
84
0
  }
85
0
  bw->free_bits -= nbits;
86
0
  if (bw->free_bits < 0) {
87
0
    bw->put_buffer <<= (bw->free_bits + nbits);
88
0
    bw->put_buffer |= (bits >> -bw->free_bits);
89
0
    DischargeBitBuffer(bw);
90
0
    bw->free_bits += 64;
91
0
    bw->put_buffer = nbits;
92
0
  }
93
0
  bw->put_buffer <<= nbits;
94
0
  bw->put_buffer |= bits;
95
0
}
Unexecuted instantiation: common.cc:jpegli::WriteBits(jpegli::JpegBitWriter*, int, unsigned long)
Unexecuted instantiation: color_transform.cc:jpegli::WriteBits(jpegli::JpegBitWriter*, int, unsigned long)
96
97
}  // namespace jpegli
98
#endif  // LIB_JPEGLI_BIT_WRITER_H_