charls-sys 2.4.5

Bindings for charls
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
// Copyright (c) Team CharLS.
// SPDX-License-Identifier: BSD-3-Clause

#include "charls/charls_jpegls_decoder.h"
#include "jpeg_stream_reader.h"
#include "util.h"

#include <memory>
#include <new>

using namespace charls;

struct charls_jpegls_decoder final
{
    void source(const const_byte_span source)
    {
        check_argument(source.data() || source.empty());
        check_operation(state_ == state::initial);

        reader_.source({source.data(), source.size()});
        state_ = state::source_set;
    }

    bool read_header(CHARLS_OUT spiff_header* spiff_header)
    {
        check_operation(state_ == state::source_set);

        bool spiff_header_found{};
        reader_.read_header(spiff_header, &spiff_header_found);
        state_ = spiff_header_found ? state::spiff_header_read : state::spiff_header_not_found;

        return spiff_header_found;
    }

    void read_header()
    {
        check_operation(state_ >= state::source_set && state_ < state::header_read);

        if (state_ != state::spiff_header_not_found)
        {
            reader_.read_header();
        }

        state_ = state::header_read;
    }

    charls::frame_info frame_info() const
    {
        check_operation(state_ >= state::header_read);
        return reader_.frame_info();
    }

    int32_t near_lossless(int32_t /*component*/ = 0) const
    {
        check_operation(state_ >= state::header_read);

        // Note: The JPEG-LS standard allows to define different NEAR parameter for every scan.
        return reader_.parameters().near_lossless;
    }

    charls::interleave_mode interleave_mode() const
    {
        check_operation(state_ >= state::header_read);

        // Note: The JPEG-LS standard allows to define different interleave modes for every scan.
        //       CharLS doesn't support mixed interleave modes, first scan determines the mode.
        return reader_.parameters().interleave_mode;
    }

    charls::color_transformation color_transformation() const
    {
        check_operation(state_ >= state::header_read);
        return reader_.parameters().transformation;
    }

    const jpegls_pc_parameters& preset_coding_parameters() const
    {
        check_operation(state_ >= state::header_read);
        return reader_.preset_coding_parameters();
    }

    size_t destination_size(const size_t stride) const
    {
        const charls::frame_info info{frame_info()};

        if (stride == auto_calculate_stride)
        {
            return checked_mul(checked_mul(checked_mul(info.component_count, info.height), info.width),
                bit_to_byte_count(info.bits_per_sample));
        }

        switch (interleave_mode())
        {
        case charls::interleave_mode::none: {
            const size_t minimum_stride{static_cast<size_t>(info.width) * bit_to_byte_count(info.bits_per_sample)};
            check_argument(stride >= minimum_stride, jpegls_errc::invalid_argument_stride);
            return checked_mul(checked_mul(stride, info.component_count), info.height) - (stride - minimum_stride);
        }

        case charls::interleave_mode::line:
        case charls::interleave_mode::sample: {
            const size_t minimum_stride{static_cast<size_t>(info.width) * info.component_count *
                                        bit_to_byte_count(info.bits_per_sample)};
            check_argument(stride >= minimum_stride, jpegls_errc::invalid_argument_stride);
            return checked_mul(stride, info.height) - (stride - minimum_stride);
        }
        }

        ASSERT(false);
        return 0;
    }

    void at_comment(const callback_function<at_comment_handler> at_comment_callback) noexcept
    {
        reader_.at_comment(at_comment_callback);
    }

    void at_application_data(const callback_function<at_application_data_handler> at_application_data_callback) noexcept
    {
        reader_.at_application_data(at_application_data_callback);
    }

    void decode(const byte_span destination, const size_t stride)
    {
        check_argument(destination.data || destination.size == 0);
        check_operation(state_ == state::header_read);

        reader_.decode(destination, stride);
        reader_.read_end_of_image();

        state_ = state::completed;
    }

    void output_bgr(const bool value) noexcept
    {
        reader_.output_bgr(value);
    }

    void region(const JlsRect& rect) noexcept
    {
        reader_.rect(rect);
    }

private:
    enum class state
    {
        initial,
        source_set,
        spiff_header_read,
        spiff_header_not_found,
        header_read,
        completed
    };

    state state_{};
    jpeg_stream_reader reader_;
};


extern "C" {

    USE_DECL_ANNOTATIONS charls_jpegls_decoder* CHARLS_API_CALLING_CONVENTION charls_jpegls_decoder_create() noexcept
    {
        MSVC_WARNING_SUPPRESS_NEXT_LINE(26402 26409)     // don't use new and delete + scoped object and move
            return new (std::nothrow) charls_jpegls_decoder; // NOLINT(cppcoreguidelines-owning-memory)
    }


    USE_DECL_ANNOTATIONS void CHARLS_API_CALLING_CONVENTION
        charls_jpegls_decoder_destroy(const charls_jpegls_decoder* decoder) noexcept
    {
        MSVC_WARNING_SUPPRESS_NEXT_LINE(26401 26409) // don't use new and delete + non-owner.
            delete decoder;                              // NOLINT(cppcoreguidelines-owning-memory)
    }


    USE_DECL_ANNOTATIONS jpegls_errc CHARLS_API_CALLING_CONVENTION charls_jpegls_decoder_set_source_buffer(
        charls_jpegls_decoder* decoder, const void* source_buffer, const size_t source_size_bytes) noexcept
        try
    {
        check_pointer(decoder)->source({source_buffer, source_size_bytes});
        return jpegls_errc::success;
    }
    catch (...)
    {
        return to_jpegls_errc();
    }


    USE_DECL_ANNOTATIONS charls_jpegls_errc CHARLS_API_CALLING_CONVENTION charls_jpegls_decoder_read_spiff_header(
        charls_jpegls_decoder* const decoder, charls_spiff_header* spiff_header, int32_t* header_found) noexcept
        try
    {
        *check_pointer(header_found) = static_cast<int32_t>(check_pointer(decoder)->read_header(check_pointer(spiff_header)));
        return jpegls_errc::success;
    }
    catch (...)
    {
        return to_jpegls_errc();
    }


    USE_DECL_ANNOTATIONS jpegls_errc CHARLS_API_CALLING_CONVENTION
        charls_jpegls_decoder_read_header(charls_jpegls_decoder* const decoder) noexcept
        try
    {
        check_pointer(decoder)->read_header();
        return jpegls_errc::success;
    }
    catch (...)
    {
        return to_jpegls_errc();
    }


    USE_DECL_ANNOTATIONS jpegls_errc CHARLS_API_CALLING_CONVENTION
        charls_jpegls_decoder_get_frame_info(const charls_jpegls_decoder* const decoder, charls_frame_info* frame_info) noexcept
        try
    {
        *check_pointer(frame_info) = check_pointer(decoder)->frame_info();
        return jpegls_errc::success;
    }
    catch (...)
    {
        return to_jpegls_errc();
    }


    USE_DECL_ANNOTATIONS charls_jpegls_errc CHARLS_API_CALLING_CONVENTION charls_jpegls_decoder_get_near_lossless(
        const charls_jpegls_decoder* decoder, const int32_t component, int32_t* near_lossless) noexcept
        try
    {
        *check_pointer(near_lossless) = check_pointer(decoder)->near_lossless(component);
        return jpegls_errc::success;
    }
    catch (...)
    {
        return to_jpegls_errc();
    }


    USE_DECL_ANNOTATIONS charls_jpegls_errc CHARLS_API_CALLING_CONVENTION charls_jpegls_decoder_get_interleave_mode(
        const charls_jpegls_decoder* decoder, charls_interleave_mode* interleave_mode) noexcept
        try
    {
        *check_pointer(interleave_mode) = check_pointer(decoder)->interleave_mode();
        return jpegls_errc::success;
    }
    catch (...)
    {
        return to_jpegls_errc();
    }


    USE_DECL_ANNOTATIONS charls_jpegls_errc CHARLS_API_CALLING_CONVENTION
        charls_jpegls_decoder_get_preset_coding_parameters(const charls_jpegls_decoder* decoder, const int32_t /*reserved*/,
            charls_jpegls_pc_parameters* preset_coding_parameters) noexcept
        try
    {
        *check_pointer(preset_coding_parameters) = check_pointer(decoder)->preset_coding_parameters();
        return jpegls_errc::success;
    }
    catch (...)
    {
        return to_jpegls_errc();
    }


    USE_DECL_ANNOTATIONS charls_jpegls_errc CHARLS_API_CALLING_CONVENTION charls_jpegls_decoder_get_color_transformation(
        const charls_jpegls_decoder* decoder, charls_color_transformation* color_transformation) noexcept
        try
    {
        *check_pointer(color_transformation) = check_pointer(decoder)->color_transformation();
        return jpegls_errc::success;
    }
    catch (...)
    {
        return to_jpegls_errc();
    }


    USE_DECL_ANNOTATIONS jpegls_errc CHARLS_API_CALLING_CONVENTION charls_jpegls_decoder_get_destination_size(
        const charls_jpegls_decoder* decoder, const uint32_t stride, size_t* destination_size_bytes) noexcept
        try
    {
        *check_pointer(destination_size_bytes) = check_pointer(decoder)->destination_size(stride);
        return jpegls_errc::success;
    }
    catch (...)
    {
        return to_jpegls_errc();
    }


    USE_DECL_ANNOTATIONS jpegls_errc CHARLS_API_CALLING_CONVENTION
        charls_jpegls_decoder_decode_to_buffer(charls_jpegls_decoder* decoder, void* destination_buffer,
            const size_t destination_size_bytes, const uint32_t stride) noexcept
        try
    {
        check_pointer(decoder)->decode({destination_buffer, destination_size_bytes}, stride);
        return jpegls_errc::success;
    }
    catch (...)
    {
        return to_jpegls_errc();
    }


    USE_DECL_ANNOTATIONS jpegls_errc CHARLS_API_CALLING_CONVENTION charls_jpegls_decoder_at_comment(
        charls_jpegls_decoder* decoder, const charls_at_comment_handler handler, void* user_context) noexcept
        try
    {
        check_pointer(decoder)->at_comment({handler, user_context});
        return jpegls_errc::success;
    }
    catch (...)
    {
        return to_jpegls_errc();
    }


    USE_DECL_ANNOTATIONS jpegls_errc CHARLS_API_CALLING_CONVENTION charls_jpegls_decoder_at_application_data(
        charls_jpegls_decoder* decoder, const charls_at_application_data_handler handler, void* user_context) noexcept
        try
    {
        check_pointer(decoder)->at_application_data({handler, user_context});
        return jpegls_errc::success;
    }
    catch (...)
    {
        return to_jpegls_errc();
    }


    USE_DECL_ANNOTATIONS jpegls_errc CHARLS_API_CALLING_CONVENTION JpegLsReadHeader(const void* source,
        const size_t source_length,
        JlsParameters* params,
        char* error_message) noexcept
        try
    {
        charls_jpegls_decoder decoder;

        decoder.source({source, source_length});
        decoder.read_header();
        *check_pointer(params) = JlsParameters{};
        const frame_info info{decoder.frame_info()};
        params->height = static_cast<int32_t>(info.height);
        params->width = static_cast<int32_t>(info.width);
        params->bitsPerSample = info.bits_per_sample;
        params->components = info.component_count;
        params->interleaveMode = decoder.interleave_mode();
        params->allowedLossyError = decoder.near_lossless();
        params->colorTransformation = decoder.color_transformation();
        const int32_t component_count{params->interleaveMode == interleave_mode::none ? 1 : params->components};
        params->stride = params->width * component_count * static_cast<int32_t>(bit_to_byte_count(params->bitsPerSample));

        const auto& preset{decoder.preset_coding_parameters()};
        params->custom.MaximumSampleValue = preset.maximum_sample_value;
        params->custom.Threshold1 = preset.threshold1;
        params->custom.Threshold2 = preset.threshold2;
        params->custom.Threshold3 = preset.threshold3;
        params->custom.ResetValue = preset.reset_value;

        clear_error_message(error_message);
        return jpegls_errc::success;
    }
    catch (...)
    {
        return set_error_message(to_jpegls_errc(), error_message);
    }


    USE_DECL_ANNOTATIONS jpegls_errc CHARLS_API_CALLING_CONVENTION JpegLsDecode(void* destination,
        const size_t destination_length,
        const void* source, const size_t source_length,
        const JlsParameters* params,
        char* error_message) noexcept
        try
    {
        charls_jpegls_decoder decoder;
        decoder.source({source, source_length});
        decoder.read_header();

        int32_t stride{};
        if (params)
        {
            decoder.output_bgr(params->outputBgr != 0);
            stride = params->stride;
        }

        decoder.decode({destination, destination_length}, static_cast<size_t>(stride));

        clear_error_message(error_message);
        return jpegls_errc::success;
    }
    catch (...)
    {
        return set_error_message(to_jpegls_errc(), error_message);
    }


    USE_DECL_ANNOTATIONS jpegls_errc CHARLS_API_CALLING_CONVENTION
        JpegLsDecodeRect(void* destination, const size_t destination_length, const void* source, const size_t source_length,
            const JlsRect roi, const JlsParameters* params, char* error_message) noexcept
        try
    {
        charls_jpegls_decoder decoder;
        decoder.source({source, source_length});
        decoder.read_header();

        int32_t stride{};
        if (params)
        {
            decoder.output_bgr(params->outputBgr != 0);
            stride = params->stride;
        }

        decoder.region(roi);
        decoder.decode({destination, destination_length}, static_cast<size_t>(stride));

        clear_error_message(error_message);
        return jpegls_errc::success;
    }
    catch (...)
    {
        return set_error_message(to_jpegls_errc(), error_message);
    }
}