Coverage Report

Created: 2025-11-16 07:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libheif/libheif/plugins/encoder_openjpeg.cc
Line
Count
Source
1
/*
2
 * OpenJPEG codec.
3
 * Copyright (c) 2023 Devon Sookhoo
4
 * Copyright (c) 2023 Dirk Farin <dirk.farin@gmail.com>
5
 *
6
 * This file is part of libheif.
7
 *
8
 * libheif is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Lesser General Public License as
10
 * published by the Free Software Foundation, either version 3 of
11
 * the License, or (at your option) any later version.
12
 *
13
 * libheif is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU Lesser General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with libheif.  If not, see <http://www.gnu.org/licenses/>.
20
 */
21
22
#include "libheif/heif.h"
23
#include "libheif/heif_plugin.h"
24
#include "encoder_openjpeg.h"
25
26
#include <openjpeg.h>
27
#include <string.h>
28
29
#include <vector>
30
#include <string>
31
#include <cassert>
32
33
using namespace std;
34
35
36
static const int OPJ_PLUGIN_PRIORITY = 80;
37
38
39
struct encoder_struct_opj
40
{
41
  int quality = 70;
42
  heif_chroma chroma = heif_chroma_undefined;
43
  opj_cparameters_t parameters;
44
45
  // --- output
46
47
  std::vector<uint8_t> codestream; //contains encoded pixel data
48
  bool data_read = false;
49
50
  // --- parameters
51
52
  // std::vector<parameter> parameters;
53
54
  // void add_param(const parameter&);
55
56
  // void add_param(const std::string& name, int value);
57
58
  // void add_param(const std::string& name, bool value);
59
60
  // void add_param(const std::string& name, const std::string& value);
61
62
  // parameter get_param(const std::string& name) const;
63
64
  // std::string preset;
65
  // std::string tune;
66
67
  // int logLevel = X265_LOG_NONE;
68
};
69
70
static const char* kParam_chroma = "chroma";
71
static const char* const kParam_chroma_valid_values[] = {
72
    "420", "422", "444", nullptr
73
};
74
75
76
0
#define MAX_PLUGIN_NAME_LENGTH 80
77
static char plugin_name[MAX_PLUGIN_NAME_LENGTH];
78
79
const char* opj_plugin_name()
80
0
{
81
0
  snprintf(plugin_name, MAX_PLUGIN_NAME_LENGTH, "OpenJPEG %s", opj_version());
82
0
  plugin_name[MAX_PLUGIN_NAME_LENGTH - 1] = 0;
83
84
0
  return plugin_name;
85
0
}
86
87
88
#define MAX_NPARAMETERS 10
89
90
static heif_encoder_parameter opj_encoder_params[MAX_NPARAMETERS];
91
static const heif_encoder_parameter* opj_encoder_parameter_ptrs[MAX_NPARAMETERS + 1];
92
93
static void opj_init_parameters()
94
252
{
95
252
  heif_encoder_parameter* p = opj_encoder_params;
96
252
  const heif_encoder_parameter** d = opj_encoder_parameter_ptrs;
97
252
  int i = 0;
98
99
252
  assert(i < MAX_NPARAMETERS);
100
252
  p->version = 2;
101
252
  p->name = kParam_chroma;
102
252
  p->type = heif_encoder_parameter_type_string;
103
  //p->string.default_value = "420";
104
252
  p->has_default = false;
105
252
  p->string.valid_values = kParam_chroma_valid_values;
106
252
  d[i++] = p++;
107
108
252
  d[i++] = nullptr;
109
252
}
110
111
void opj_init_plugin()
112
252
{
113
252
  opj_init_parameters();
114
252
}
115
116
void opj_cleanup_plugin()
117
0
{
118
0
}
119
120
static void opj_set_default_parameters(void* encoder);
121
122
heif_error opj_new_encoder(void** encoder_out)
123
0
{
124
0
  encoder_struct_opj* encoder = new encoder_struct_opj();
125
0
  *encoder_out = encoder;
126
127
0
  opj_set_default_parameters(encoder);
128
0
  opj_set_default_encoder_parameters(&(encoder->parameters));
129
130
0
  return heif_error_ok;
131
0
}
132
133
void opj_free_encoder(void* encoder_raw)
134
0
{
135
0
  encoder_struct_opj* encoder = (encoder_struct_opj*) encoder_raw;
136
0
  delete encoder;
137
0
}
138
139
heif_error opj_set_parameter_quality(void* encoder_raw, int quality)
140
0
{
141
0
  auto* encoder = (encoder_struct_opj*) encoder_raw;
142
143
0
  if (quality < 0 || quality > 100) {
144
0
    return heif_error_invalid_parameter_value;
145
0
  }
146
147
0
  encoder->quality = quality;
148
149
0
  return heif_error_ok;
150
0
}
151
152
heif_error opj_get_parameter_quality(void* encoder_raw, int* quality)
153
0
{
154
0
  auto* encoder = (encoder_struct_opj*) encoder_raw;
155
156
0
  *quality = encoder->quality;
157
158
0
  return heif_error_ok;
159
0
}
160
161
heif_error opj_set_parameter_lossless(void* encoder_raw, int lossless)
162
0
{
163
0
  auto* encoder = (encoder_struct_opj*) encoder_raw;
164
0
  encoder->parameters.irreversible = lossless ? 0 : 1;
165
0
  return heif_error_ok;
166
0
}
167
168
heif_error opj_get_parameter_lossless(void* encoder_raw, int* lossless)
169
0
{
170
0
  auto* encoder = (encoder_struct_opj*) encoder_raw;
171
0
  *lossless = (encoder->parameters.irreversible == 0);
172
0
  return heif_error_ok;
173
0
}
174
175
heif_error opj_set_parameter_logging_level(void* encoder, int logging)
176
0
{
177
0
  return heif_error_ok;
178
0
}
179
180
heif_error opj_get_parameter_logging_level(void* encoder, int* logging)
181
0
{
182
0
  return heif_error_ok;
183
0
}
184
185
const heif_encoder_parameter** opj_list_parameters(void* encoder)
186
0
{
187
0
  return opj_encoder_parameter_ptrs;
188
0
}
189
190
heif_error opj_set_parameter_integer(void* encoder_raw, const char* name, int value)
191
0
{
192
0
  encoder_struct_opj* encoder = (encoder_struct_opj*) encoder_raw;
193
194
0
  if (strcmp(name, heif_encoder_parameter_name_quality) == 0) {
195
0
    return opj_set_parameter_quality(encoder, value);
196
0
  }
197
198
0
  return heif_error_unsupported_parameter;
199
0
}
200
201
heif_error opj_get_parameter_integer(void* encoder_raw, const char* name, int* value)
202
0
{
203
0
  encoder_struct_opj* encoder = (encoder_struct_opj*) encoder_raw;
204
205
0
  if (strcmp(name, heif_encoder_parameter_name_quality) == 0) {
206
0
    return opj_get_parameter_quality(encoder, value);
207
0
  }
208
209
0
  return heif_error_ok;
210
0
}
211
212
heif_error opj_set_parameter_boolean(void* encoder, const char* name, int value)
213
0
{
214
0
  return heif_error_ok;
215
0
}
216
217
heif_error opj_get_parameter_boolean(void* encoder, const char* name, int* value)
218
0
{
219
0
  return heif_error_ok;
220
0
}
221
222
heif_error opj_set_parameter_string(void* encoder_raw, const char* name, const char* value)
223
0
{
224
0
  auto* encoder = (encoder_struct_opj*) encoder_raw;
225
226
0
  if (strcmp(name, kParam_chroma) == 0) {
227
0
    if (strcmp(value, "420") == 0) {
228
0
      encoder->chroma = heif_chroma_420;
229
0
      return heif_error_ok;
230
0
    }
231
0
    else if (strcmp(value, "422") == 0) {
232
0
      encoder->chroma = heif_chroma_422;
233
0
      return heif_error_ok;
234
0
    }
235
0
    else if (strcmp(value, "444") == 0) {
236
0
      encoder->chroma = heif_chroma_444;
237
0
      return heif_error_ok;
238
0
    }
239
0
    else {
240
0
      return heif_error_invalid_parameter_value;
241
0
    }
242
0
  }
243
244
0
  return heif_error_unsupported_parameter;
245
0
}
246
247
static void save_strcpy(char* dst, int dst_size, const char* src)
248
0
{
249
0
  strncpy(dst, src, dst_size - 1);
250
0
  dst[dst_size - 1] = 0;
251
0
}
252
253
heif_error opj_get_parameter_string(void* encoder_raw, const char* name, char* value, int value_size)
254
0
{
255
0
  encoder_struct_opj* encoder = (encoder_struct_opj*) encoder_raw;
256
257
0
  if (strcmp(name, kParam_chroma) == 0) {
258
0
    switch (encoder->chroma) {
259
0
      case heif_chroma_420:
260
0
        save_strcpy(value, value_size, "420");
261
0
        break;
262
0
      case heif_chroma_422:
263
0
        save_strcpy(value, value_size, "422");
264
0
        break;
265
0
      case heif_chroma_444:
266
0
        save_strcpy(value, value_size, "444");
267
0
        break;
268
0
      case heif_chroma_undefined:
269
0
        save_strcpy(value, value_size, "undefined");
270
0
        break;
271
0
      default:
272
0
        assert(false);
273
0
        return heif_error_invalid_parameter_value;
274
0
      }
275
0
      return heif_error_ok;
276
0
  }
277
278
0
  return heif_error_unsupported_parameter;
279
0
}
280
281
282
static void opj_set_default_parameters(void* encoder)
283
0
{
284
0
  for (const heif_encoder_parameter** p = opj_encoder_parameter_ptrs; *p; p++) {
285
0
    const heif_encoder_parameter* param = *p;
286
287
0
    if (param->has_default) {
288
0
      switch (param->type) {
289
0
        case heif_encoder_parameter_type_integer:
290
0
          opj_set_parameter_integer(encoder, param->name, param->integer.default_value);
291
0
          break;
292
0
        case heif_encoder_parameter_type_boolean:
293
0
          opj_set_parameter_boolean(encoder, param->name, param->boolean.default_value);
294
0
          break;
295
0
        case heif_encoder_parameter_type_string:
296
0
          opj_set_parameter_string(encoder, param->name, param->string.default_value);
297
0
          break;
298
0
      }
299
0
    }
300
0
  }
301
0
}
302
303
304
void opj_query_input_colorspace(heif_colorspace* inout_colorspace, heif_chroma* inout_chroma)
305
0
{
306
  // Replace the input colorspace/chroma with the one that is supported by the encoder and that
307
  // comes as close to the input colorspace/chroma as possible.
308
309
0
  if (*inout_colorspace == heif_colorspace_monochrome) {
310
0
    *inout_colorspace = heif_colorspace_monochrome;
311
0
    *inout_chroma = heif_chroma_monochrome;
312
0
  }
313
0
  else {
314
0
    *inout_colorspace = heif_colorspace_YCbCr;
315
0
    *inout_chroma = heif_chroma_444;
316
0
  }
317
0
}
318
319
void opj_query_input_colorspace2(void* encoder_raw, heif_colorspace* inout_colorspace, heif_chroma* inout_chroma)
320
0
{
321
0
  auto* encoder = (struct encoder_struct_opj*) encoder_raw;
322
323
0
  if (*inout_colorspace == heif_colorspace_monochrome) {
324
0
    *inout_colorspace = heif_colorspace_monochrome;
325
0
    *inout_chroma = heif_chroma_monochrome;
326
0
  }
327
0
  else {
328
0
    *inout_colorspace = heif_colorspace_YCbCr;
329
330
0
    if (encoder->chroma != heif_chroma_undefined) {
331
0
      *inout_chroma = encoder->chroma;
332
0
    }
333
0
    else {
334
0
      *inout_chroma = heif_chroma_444;
335
0
    }
336
0
  }
337
0
}
338
339
340
// OpenJPEG will encode a portion of the image and then call this function
341
// @param src_data_raw - Newly encoded bytes provided by OpenJPEG
342
// @param nb_bytes - The number of bytes or size of src_data_raw
343
// @param encoder_raw - Out the new
344
// @return - The number of bytes successfully transferred
345
static OPJ_SIZE_T opj_write_from_buffer(void* src_data_raw, OPJ_SIZE_T nb_bytes, void* encoder_raw)
346
0
{
347
0
  uint8_t* src_data = (uint8_t*) src_data_raw;
348
0
  encoder_struct_opj* encoder = (encoder_struct_opj*) encoder_raw;
349
350
0
  for (size_t i = 0; i < nb_bytes; i++) {
351
0
    encoder->codestream.push_back(src_data[i]);
352
0
  }
353
354
0
  return nb_bytes;
355
0
}
356
357
static void opj_close_from_buffer(void* p_user_data)
358
0
{
359
0
}
360
361
362
// The codestream is defined in ISO/IEC 15444-1. It contains the
363
// compressed image pixel data and very basic metadata. 
364
// @param data - Uncompressed image pixel data
365
// @param encoder - The function will output codestream in encoder->codestream
366
static heif_error generate_codestream(opj_image_t* image, encoder_struct_opj* encoder)
367
0
{
368
0
  heif_error error;
369
0
  OPJ_BOOL success;
370
371
0
  encoder->parameters.cp_disto_alloc = 1;
372
0
  encoder->parameters.tcp_numlayers = 1;
373
0
  encoder->parameters.tcp_rates[0] = (float)(1 + (100 - encoder->quality)/2);
374
375
#if 0
376
  //Insert a human readable comment into the codestream
377
  if (parameters.cp_comment == NULL) {
378
    char buf[80];
379
#ifdef _WIN32
380
    sprintf_s(buf, 80, "Created by OpenJPEG version %s", opj_version());
381
#else
382
    snprintf(buf, 80, "Created by OpenJPEG version %s", opj_version());
383
#endif
384
    parameters.cp_comment = strdup(buf);
385
  }
386
#endif
387
388
  //OPJ_CODEC_J2K - Only generate the codestream
389
  //OPJ_CODEC_JP2 - Generate the entire jp2 file (which contains a codestream)
390
0
  OPJ_CODEC_FORMAT codec_format = OPJ_CODEC_J2K;
391
0
  opj_codec_t* codec = opj_create_compress(codec_format);
392
0
  success = opj_setup_encoder(codec, &(encoder->parameters), image);
393
0
  if (!success) {
394
0
    opj_destroy_codec(codec);
395
0
    error = {heif_error_Encoding_error, heif_suberror_Unspecified, "Failed to setup OpenJPEG encoder"};
396
0
    return error;
397
0
  }
398
399
400
  //Create Stream
401
0
  size_t bufferSize = 64 * 1024; // 64k
402
0
  opj_stream_t* stream = opj_stream_create(bufferSize, false /* read only mode */);
403
0
  if (stream == NULL) {
404
0
    opj_destroy_codec(codec);
405
0
    error = {heif_error_Encoding_error, heif_suberror_Unspecified, "Failed to create opj_stream_t"};
406
0
    return error;
407
0
  }
408
409
410
  // When OpenJPEG encodes the image, it will pass the 'encoder' into the write function
411
0
  opj_stream_set_user_data(stream, encoder, opj_close_from_buffer);
412
413
  // Tell OpenJPEG how and where to write the output data
414
0
  opj_stream_set_write_function(stream, (opj_stream_write_fn) opj_write_from_buffer);
415
416
  // TODO: should we use this function?
417
  // opj_stream_set_user_data_length(stream, 0);
418
419
420
421
0
  success = opj_start_compress(codec, image, stream);
422
0
  if (!success) {
423
0
    opj_stream_destroy(stream);
424
0
    opj_destroy_codec(codec);
425
0
    error = {heif_error_Encoding_error, heif_suberror_Unspecified, "Failed opj_start_compress()"};
426
0
    return error;
427
0
  }
428
429
0
  success = opj_encode(codec, stream);
430
0
  if (!success) {
431
0
    opj_stream_destroy(stream);
432
0
    opj_destroy_codec(codec);
433
0
    error = {heif_error_Encoding_error, heif_suberror_Unspecified, "Failed opj_encode()"};
434
0
    return error;
435
0
  }
436
437
0
  success = opj_end_compress(codec, stream);
438
0
  if (!success) {
439
0
    opj_stream_destroy(stream);
440
0
    opj_destroy_codec(codec);
441
0
    error = {heif_error_Encoding_error, heif_suberror_Unspecified, "Failed opj_end_compress()"};
442
0
    return error;
443
0
  }
444
445
0
  opj_stream_destroy(stream);
446
0
  opj_destroy_codec(codec);
447
448
0
  return heif_error_ok;
449
0
}
450
451
452
heif_error opj_encode_image(void* encoder_raw, const heif_image* image, heif_image_input_class image_class)
453
0
{
454
0
  encoder_struct_opj* encoder = (encoder_struct_opj*) encoder_raw;
455
0
  heif_error err;
456
457
0
  heif_chroma chroma = heif_image_get_chroma_format(image);
458
0
  heif_colorspace colorspace = heif_image_get_colorspace(image);
459
460
0
  int width = heif_image_get_primary_width(image);
461
0
  int height = heif_image_get_primary_height(image);
462
463
0
  std::vector<heif_channel> channels;
464
0
  OPJ_COLOR_SPACE opj_colorspace;
465
466
0
  switch (colorspace) {
467
0
    case heif_colorspace_YCbCr:
468
0
      channels = {heif_channel_Y, heif_channel_Cb, heif_channel_Cr};
469
0
      opj_colorspace = OPJ_CLRSPC_SYCC;
470
0
      break;
471
0
    case heif_colorspace_RGB:
472
0
      channels = {heif_channel_R, heif_channel_G, heif_channel_B};
473
0
      opj_colorspace = OPJ_CLRSPC_SRGB;
474
0
      break;
475
0
    case heif_colorspace_monochrome:
476
0
      channels = {heif_channel_Y};
477
0
      opj_colorspace = OPJ_CLRSPC_GRAY;
478
0
      break;
479
0
    default:
480
0
      assert(false);
481
0
      return {heif_error_Encoding_error, heif_suberror_Unspecified, "OpenJPEG encoder plugin received image with invalid colorspace."};
482
0
  }
483
484
0
  int band_count = (int) channels.size();
485
486
0
  opj_image_cmptparm_t component_params[4];
487
0
  memset(&component_params, 0, band_count * sizeof(opj_image_cmptparm_t));
488
489
0
  for (int comp = 0; comp < band_count; comp++) {
490
491
0
    int bpp = heif_image_get_bits_per_pixel_range(image, channels[comp]);
492
493
0
    int sub_dx = 1, sub_dy = 1;
494
0
    switch (chroma) {
495
0
      case heif_chroma_420:
496
0
        sub_dx = 2;
497
0
        sub_dy = 2;
498
0
        break;
499
0
      case heif_chroma_422:
500
0
        sub_dx = 2;
501
0
        sub_dy = 1;
502
0
        break;
503
0
      default:
504
0
        break;
505
0
    }
506
507
0
    component_params[comp].prec = bpp;
508
0
    component_params[comp].sgnd = 0;
509
0
    component_params[comp].dx = comp == 0 ? 1 : sub_dx;
510
0
    component_params[comp].dy = comp == 0 ? 1 : sub_dy;
511
0
    component_params[comp].w = comp == 0 ? width : (width + sub_dx / 2) / sub_dx;
512
0
    component_params[comp].h = comp == 0 ? height : (height + sub_dy / 2) / sub_dy;
513
0
  }
514
515
0
  opj_image_t* opj_image = opj_image_create(band_count, &component_params[0], opj_colorspace);
516
0
  if (image == nullptr) {
517
    // Failed to create image
518
0
    err = {heif_error_Encoding_error, heif_suberror_Unspecified, "Failed create OpenJPEG image"};
519
0
    return err;
520
0
  }
521
522
0
  opj_image->x0 = 0;
523
0
  opj_image->y0 = 0;
524
0
  opj_image->x1 = width;
525
0
  opj_image->y1 = height;
526
527
0
  for (int comp = 0; comp < band_count; comp++) {
528
0
    int stride;
529
0
    const uint8_t* p = heif_image_get_plane_readonly(image, channels[comp], &stride);
530
0
    int bpp = heif_image_get_bits_per_pixel(image, channels[comp]);
531
532
0
    int cwidth = component_params[comp].w;
533
0
    int cheight = component_params[comp].h;
534
535
    // Note: obj_image data is 32bit integer
536
537
0
    if (bpp <= 8) {
538
0
      for (int y = 0; y < cheight; y++) {
539
0
        for (int x = 0; x < cwidth; x++) {
540
0
          opj_image->comps[comp].data[y * cwidth + x] = p[y * stride + x];
541
0
        }
542
0
      }
543
0
    }
544
0
    else {
545
0
      const uint16_t* p16 = (const uint16_t*)p;
546
547
0
      for (int y = 0; y < cheight; y++) {
548
0
        for (int x = 0; x < cwidth; x++) {
549
0
          opj_image->comps[comp].data[y * cwidth + x] = p16[y * stride/2 + x];
550
0
        }
551
0
      }
552
0
    }
553
0
  }
554
555
0
  encoder->data_read = false;
556
0
  encoder->codestream.clear(); //Fixes issue when encoding multiple images and old data persists.
557
558
  //Encodes the image into a 'codestream' which is stored in the 'encoder' variable
559
0
  err = generate_codestream(opj_image, encoder);
560
561
0
  opj_image_destroy(opj_image);
562
563
0
  return err;
564
0
}
565
566
heif_error opj_get_compressed_data(void* encoder_raw, uint8_t** data, int* size, enum heif_encoded_data_type* type)
567
0
{
568
  // Get a packet of decoded data. The data format depends on the codec.
569
570
0
  encoder_struct_opj* encoder = (encoder_struct_opj*) encoder_raw;
571
572
0
  if (encoder->data_read) {
573
0
    *size = 0;
574
0
    *data = nullptr;
575
0
  }
576
0
  else {
577
0
    *size = (int) encoder->codestream.size();
578
0
    *data = encoder->codestream.data();
579
0
    encoder->data_read = true;
580
0
  }
581
582
0
  return heif_error_ok;
583
0
}
584
585
void opj_query_encoded_size(void* encoder, uint32_t input_width, uint32_t input_height, uint32_t* encoded_width, uint32_t* encoded_height)
586
0
{
587
  // --- version 3 ---
588
589
  // The encoded image size may be different from the input frame size, e.g. because
590
  // of required rounding, or a required minimum size. Use this function to return
591
  // the encoded size for a given input image size.
592
  // You may set this to NULL if no padding is required for any image size.
593
594
0
  *encoded_width = input_width;
595
0
  *encoded_height = input_height;
596
0
}
597
598
599
static const heif_encoder_plugin encoder_plugin_openjpeg{
600
    /* plugin_api_version */ 3,
601
    /* compression_format */ heif_compression_JPEG2000,
602
    /* id_name */ "openjpeg",
603
    /* priority */ OPJ_PLUGIN_PRIORITY,
604
    /* supports_lossy_compression */ false,
605
    /* supports_lossless_compression */ true,
606
    /* get_plugin_name */ opj_plugin_name,
607
    /* init_plugin */ opj_init_plugin,
608
    /* cleanup_plugin */ opj_cleanup_plugin,
609
    /* new_encoder */ opj_new_encoder,
610
    /* free_encoder */ opj_free_encoder,
611
    /* set_parameter_quality */ opj_set_parameter_quality,
612
    /* get_parameter_quality */ opj_get_parameter_quality,
613
    /* set_parameter_lossless */ opj_set_parameter_lossless,
614
    /* get_parameter_lossless */ opj_get_parameter_lossless,
615
    /* set_parameter_logging_level */ opj_set_parameter_logging_level,
616
    /* get_parameter_logging_level */ opj_get_parameter_logging_level,
617
    /* list_parameters */ opj_list_parameters,
618
    /* set_parameter_integer */ opj_set_parameter_integer,
619
    /* get_parameter_integer */ opj_get_parameter_integer,
620
    /* set_parameter_boolean */ opj_set_parameter_boolean,
621
    /* get_parameter_boolean */ opj_get_parameter_boolean,
622
    /* set_parameter_string */ opj_set_parameter_string,
623
    /* get_parameter_string */ opj_get_parameter_string,
624
    /* query_input_colorspace */ opj_query_input_colorspace,
625
    /* encode_image */ opj_encode_image,
626
    /* get_compressed_data */ opj_get_compressed_data,
627
    /* query_input_colorspace (v2) */ opj_query_input_colorspace2,
628
    /* query_encoded_size (v3) */ opj_query_encoded_size
629
};
630
631
const heif_encoder_plugin* get_encoder_plugin_openjpeg()
632
252
{
633
252
  return &encoder_plugin_openjpeg;
634
252
}
635
636
637
#if PLUGIN_OPENJPEG_ENCODER
638
heif_plugin_info plugin_info {
639
  1,
640
  heif_plugin_type_encoder,
641
  &encoder_plugin_openjpeg
642
};
643
#endif