Coverage Report

Created: 2025-10-12 07:48

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libheif/libheif/codecs/jpeg_enc.cc
Line
Count
Source
1
/*
2
 * HEIF codec.
3
 * Copyright (c) 2024 Dirk Farin <dirk.farin@gmail.com>
4
 *
5
 * This file is part of libheif.
6
 *
7
 * libheif is free software: you can redistribute it and/or modify
8
 * it under the terms of the GNU Lesser General Public License as
9
 * published by the Free Software Foundation, either version 3 of
10
 * the License, or (at your option) any later version.
11
 *
12
 * libheif is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public License
18
 * along with libheif.  If not, see <http://www.gnu.org/licenses/>.
19
 */
20
21
#include "jpeg_enc.h"
22
#include "jpeg_boxes.h"
23
#include "error.h"
24
#include "context.h"
25
#include "api_structs.h"
26
#include <cstring>
27
28
#include <string>
29
30
31
static uint8_t JPEG_SOS = 0xDA;
32
33
34
const heif_color_profile_nclx* Encoder_JPEG::get_forced_output_nclx() const
35
0
{
36
  // JPEG always uses CCIR-601
37
38
0
  static heif_color_profile_nclx target_heif_nclx;
39
0
  target_heif_nclx.version = 1;
40
0
  target_heif_nclx.matrix_coefficients = heif_matrix_coefficients_ITU_R_BT_601_6;
41
0
  target_heif_nclx.color_primaries = heif_color_primaries_ITU_R_BT_601_6;
42
0
  target_heif_nclx.transfer_characteristics = heif_transfer_characteristic_ITU_R_BT_601_6;
43
0
  target_heif_nclx.full_range_flag = true;
44
45
0
  return &target_heif_nclx;
46
0
}
47
48
49
Result<Encoder::CodedImageData> Encoder_JPEG::encode(const std::shared_ptr<HeifPixelImage>& image,
50
                                                     struct heif_encoder* encoder,
51
                                                     const struct heif_encoding_options& options,
52
                                                     enum heif_image_input_class input_class)
53
0
{
54
0
  Encoder::CodedImageData codedImage;
55
56
57
0
  heif_image c_api_image;
58
0
  c_api_image.image = image;
59
60
0
  struct heif_error err = encoder->plugin->encode_image(encoder->encoder, &c_api_image, input_class);
61
0
  if (err.code) {
62
0
    return Error(err.code,
63
0
                 err.subcode,
64
0
                 err.message);
65
0
  }
66
67
0
  std::vector<uint8_t> vec;
68
69
0
  for (;;) {
70
0
    uint8_t* data;
71
0
    int size;
72
73
0
    encoder->plugin->get_compressed_data(encoder->encoder, &data, &size, nullptr);
74
75
0
    if (data == nullptr) {
76
0
      break;
77
0
    }
78
79
0
    size_t oldsize = vec.size();
80
0
    vec.resize(oldsize + size);
81
0
    memcpy(vec.data() + oldsize, data, size);
82
0
  }
83
84
#if 0
85
  // Optional: split the JPEG data into a jpgC box and the actual image data.
86
  // Currently disabled because not supported yet in other decoders.
87
  if (false) {
88
    size_t pos = find_jpeg_marker_start(vec, JPEG_SOS);
89
    if (pos > 0) {
90
      std::vector<uint8_t> jpgC_data(vec.begin(), vec.begin() + pos);
91
      auto jpgC = std::make_shared<Box_jpgC>();
92
      jpgC->set_data(jpgC_data);
93
94
      auto ipma_box = m_heif_file->get_ipma_box();
95
      int index = m_heif_file->get_ipco_box()->find_or_append_child_box(jpgC);
96
      ipma_box->add_property_for_item_ID(image_id, Box_ipma::PropertyAssociation{true, uint16_t(index + 1)});
97
98
      std::vector<uint8_t> image_data(vec.begin() + pos, vec.end());
99
      vec = std::mo ve(image_data);
100
    }
101
  }
102
#endif
103
0
  (void) JPEG_SOS;
104
105
0
  codedImage.bitstream = std::move(vec);
106
107
#if 0
108
  // TODO: extract 'jpgC' header data
109
#endif
110
111
0
  codedImage.codingConstraints.intra_pred_used = false;
112
0
  codedImage.codingConstraints.all_ref_pics_intra = true;
113
0
  codedImage.codingConstraints.max_ref_per_pic = 0;
114
115
0
  return {codedImage};
116
0
}
117
118
119
std::shared_ptr<class Box_VisualSampleEntry> Encoder_JPEG::get_sample_description_box(const CodedImageData& data) const
120
0
{
121
0
  auto mjpg = std::make_shared<Box_mjpg>();
122
0
  mjpg->get_VisualSampleEntry().compressorname = "JPEG";
123
124
0
  for (auto prop : data.properties) {
125
0
    if (prop->get_short_type() == fourcc("jpgC")) {
126
0
      mjpg->append_child_box(prop);
127
0
    }
128
0
  }
129
130
0
  return mjpg;
131
0
}