openjp2/
openjpeg.rs

1/*
2 * The copyright in this software is being made available under the 2-clauses
3 * BSD License, included below. This software may be subject to other third
4 * party and contributor rights, including patent rights, and no such rights
5 * are granted under this license.
6 *
7 * Copyright (c) 2005, Herve Drolon, FreeImage Team
8 * Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR
9 * Copyright (c) 2012, CS Systemes d'Information, France
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 *    notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 *    notice, this list of conditions and the following disclaimer in the
19 *    documentation and/or other materials provided with the distribution.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 */
33
34pub use crate::c_api_types::*;
35pub use crate::consts::opj::*;
36pub use crate::image::{opj_image_create, opj_image_destroy, opj_image_tile_create};
37
38use crate::j2k::*;
39pub(crate) use crate::types::*;
40
41use crate::codec::*;
42use crate::malloc::*;
43
44#[cfg(not(feature = "std"))]
45use alloc::{boxed::Box, vec::Vec};
46
47#[cfg(feature = "file-io")]
48use ::libc::FILE;
49
50/* ---------------------------------------------------------------------- */
51/* Functions to set the message handlers */
52#[no_mangle]
53pub unsafe fn opj_set_info_handler(
54  mut p_codec: *mut opj_codec_t,
55  mut p_callback: opj_msg_callback,
56  mut p_user_data: *mut core::ffi::c_void,
57) -> OPJ_BOOL {
58  if p_codec.is_null() {
59    return 0i32;
60  }
61  let l_codec = &mut *(p_codec as *mut opj_codec_private_t);
62  l_codec.set_info_handler(p_callback, p_user_data)
63}
64
65#[no_mangle]
66pub unsafe fn opj_set_warning_handler(
67  mut p_codec: *mut opj_codec_t,
68  mut p_callback: opj_msg_callback,
69  mut p_user_data: *mut core::ffi::c_void,
70) -> OPJ_BOOL {
71  if p_codec.is_null() {
72    return 0i32;
73  }
74  let l_codec = &mut *(p_codec as *mut opj_codec_private_t);
75  l_codec.set_warning_handler(p_callback, p_user_data)
76}
77
78#[no_mangle]
79pub unsafe fn opj_set_error_handler(
80  mut p_codec: *mut opj_codec_t,
81  mut p_callback: opj_msg_callback,
82  mut p_user_data: *mut core::ffi::c_void,
83) -> OPJ_BOOL {
84  if p_codec.is_null() {
85    return 0i32;
86  }
87  let l_codec = &mut *(p_codec as *mut opj_codec_private_t);
88  l_codec.set_error_handler(p_callback, p_user_data)
89}
90
91/* ---------------------------------------------------------------------- */
92pub const OPJ_VERSION: &str = "2.5.2";
93pub const OPJ_VERSION_C: *const u8 = b"2.5.2\x00" as *const u8;
94
95#[no_mangle]
96pub fn opj_version() -> *const core::ffi::c_char {
97  OPJ_VERSION_C as *const core::ffi::c_char
98}
99
100/* ---------------------------------------------------------------------- */
101/* DECOMPRESSION FUNCTIONS*/
102#[no_mangle]
103pub fn opj_create_decompress(mut p_format: OPJ_CODEC_FORMAT) -> *mut opj_codec_t {
104  if let Some(codec) = opj_codec_private_t::new_decoder(p_format) {
105    let l_codec = Box::new(codec);
106    Box::into_raw(l_codec) as *mut opj_codec_t
107  } else {
108    core::ptr::null_mut()
109  }
110}
111
112#[no_mangle]
113pub unsafe fn opj_set_default_decoder_parameters(mut parameters: *mut opj_dparameters_t) {
114  if parameters.is_null() {
115    return;
116  }
117  let parameters = &mut *parameters;
118  parameters.set_defaults();
119}
120
121#[no_mangle]
122pub unsafe fn opj_codec_set_threads(
123  mut p_codec: *mut opj_codec_t,
124  mut num_threads: core::ffi::c_int,
125) -> OPJ_BOOL {
126  if p_codec.is_null() {
127    return 0i32;
128  }
129  let l_codec = &mut *(p_codec as *mut opj_codec_private_t);
130  l_codec.set_threads(num_threads)
131}
132
133#[no_mangle]
134pub unsafe fn opj_setup_decoder(
135  mut p_codec: *mut opj_codec_t,
136  mut parameters: *mut opj_dparameters_t,
137) -> OPJ_BOOL {
138  if p_codec.is_null() || parameters.is_null() {
139    return 0i32;
140  }
141  let l_codec = &mut *(p_codec as *mut opj_codec_private_t);
142  let parameters = &mut *parameters;
143  l_codec.setup_decoder(parameters)
144}
145
146#[no_mangle]
147pub unsafe fn opj_decoder_set_strict_mode(
148  mut p_codec: *mut opj_codec_t,
149  mut strict: OPJ_BOOL,
150) -> OPJ_BOOL {
151  if p_codec.is_null() {
152    return 0i32;
153  }
154  let l_codec = &mut *(p_codec as *mut opj_codec_private_t);
155  l_codec.decoder_set_strict_mode(strict)
156}
157
158#[no_mangle]
159pub unsafe fn opj_read_header(
160  mut p_stream: *mut opj_stream_t,
161  mut p_codec: *mut opj_codec_t,
162  mut p_image: *mut *mut opj_image_t,
163) -> OPJ_BOOL {
164  if p_codec.is_null() | p_stream.is_null() | p_image.is_null() {
165    return 0i32;
166  }
167  let p_stream = unsafe { &mut *(p_stream as *mut opj_stream_private_t) };
168  let l_codec = &mut *(p_codec as *mut opj_codec_private_t);
169  match l_codec.read_header(p_stream) {
170    Some(image) => {
171      *p_image = Box::into_raw(image);
172      1
173    }
174    None => 0,
175  }
176}
177
178#[no_mangle]
179pub unsafe fn opj_set_decoded_components(
180  mut p_codec: *mut opj_codec_t,
181  mut numcomps: OPJ_UINT32,
182  mut comps_indices: *const OPJ_UINT32,
183  mut apply_color_transforms: OPJ_BOOL,
184) -> OPJ_BOOL {
185  if p_codec.is_null() {
186    return 0i32;
187  }
188  let l_codec = &mut *(p_codec as *mut opj_codec_private_t);
189  let components = unsafe { core::slice::from_raw_parts(comps_indices, numcomps as usize) };
190  l_codec.set_decoded_components(components, apply_color_transforms)
191}
192
193#[no_mangle]
194pub unsafe fn opj_decode(
195  mut p_codec: *mut opj_codec_t,
196  mut p_stream: *mut opj_stream_t,
197  mut p_image: *mut opj_image_t,
198) -> OPJ_BOOL {
199  if p_codec.is_null() | p_stream.is_null() | p_image.is_null() {
200    return 0i32;
201  }
202  let p_image = unsafe { &mut *p_image };
203  let p_stream = unsafe { &mut *(p_stream as *mut opj_stream_private_t) };
204  let l_codec = &mut *(p_codec as *mut opj_codec_private_t);
205  l_codec.decode(p_stream, p_image)
206}
207
208#[no_mangle]
209pub unsafe fn opj_set_decode_area(
210  mut p_codec: *mut opj_codec_t,
211  mut p_image: *mut opj_image_t,
212  mut p_start_x: OPJ_INT32,
213  mut p_start_y: OPJ_INT32,
214  mut p_end_x: OPJ_INT32,
215  mut p_end_y: OPJ_INT32,
216) -> OPJ_BOOL {
217  if p_codec.is_null() | p_image.is_null() {
218    return 0i32;
219  }
220  let p_image = unsafe { &mut *p_image };
221  let l_codec = &mut *(p_codec as *mut opj_codec_private_t);
222  l_codec.set_decode_area(p_image, p_start_x, p_start_y, p_end_x, p_end_y)
223}
224
225#[no_mangle]
226pub unsafe fn opj_read_tile_header(
227  mut p_codec: *mut opj_codec_t,
228  mut p_stream: *mut opj_stream_t,
229  mut p_tile_index: *mut OPJ_UINT32,
230  mut p_data_size: *mut OPJ_UINT32,
231  mut p_tile_x0: *mut OPJ_INT32,
232  mut p_tile_y0: *mut OPJ_INT32,
233  mut p_tile_x1: *mut OPJ_INT32,
234  mut p_tile_y1: *mut OPJ_INT32,
235  mut p_nb_comps: *mut OPJ_UINT32,
236  mut p_should_go_on: *mut OPJ_BOOL,
237) -> OPJ_BOOL {
238  if p_codec.is_null() | p_stream.is_null() {
239    return 0i32;
240  }
241  let p_stream = unsafe { &mut *(p_stream as *mut opj_stream_private_t) };
242  let l_codec = &mut *(p_codec as *mut opj_codec_private_t);
243  let mut tile_info = TileInfo::default();
244  if !p_data_size.is_null() {
245    // Request the tile data size.
246    tile_info.data_size = Some(0);
247  }
248  if l_codec.read_tile_header(p_stream, &mut tile_info) {
249    unsafe {
250      if !p_tile_index.is_null() {
251        *p_tile_index = tile_info.index;
252      }
253      if !p_data_size.is_null() {
254        *p_data_size = tile_info.data_size.unwrap_or_default();
255      }
256      if !p_tile_x0.is_null() {
257        *p_tile_x0 = tile_info.x0;
258      }
259      if !p_tile_y0.is_null() {
260        *p_tile_y0 = tile_info.y0;
261      }
262      if !p_tile_x1.is_null() {
263        *p_tile_x1 = tile_info.x1;
264      }
265      if !p_tile_y1.is_null() {
266        *p_tile_y1 = tile_info.y1;
267      }
268      if !p_nb_comps.is_null() {
269        *p_nb_comps = tile_info.nb_comps;
270      }
271      if !p_should_go_on.is_null() {
272        *p_should_go_on = tile_info.go_on as _;
273      }
274    }
275    1
276  } else {
277    0
278  }
279}
280
281#[no_mangle]
282pub unsafe fn opj_decode_tile_data(
283  mut p_codec: *mut opj_codec_t,
284  mut p_tile_index: OPJ_UINT32,
285  mut p_data: *mut OPJ_BYTE,
286  mut p_data_size: OPJ_UINT32,
287  mut p_stream: *mut opj_stream_t,
288) -> OPJ_BOOL {
289  if p_codec.is_null() | p_stream.is_null() {
290    return 0i32;
291  }
292  let p_stream = unsafe { &mut *(p_stream as *mut opj_stream_private_t) };
293  let l_codec = &mut *(p_codec as *mut opj_codec_private_t);
294  let p_data = if p_data.is_null() {
295    None
296  } else {
297    Some(unsafe { core::slice::from_raw_parts_mut(p_data as *mut u8, p_data_size as usize) })
298  };
299  l_codec.decode_tile_data(p_stream, p_tile_index, p_data)
300}
301
302#[no_mangle]
303pub unsafe fn opj_get_decoded_tile(
304  mut p_codec: *mut opj_codec_t,
305  mut p_stream: *mut opj_stream_t,
306  mut p_image: *mut opj_image_t,
307  mut tile_index: OPJ_UINT32,
308) -> OPJ_BOOL {
309  if p_codec.is_null() | p_stream.is_null() | p_image.is_null() {
310    return 0i32;
311  }
312  let p_image = unsafe { &mut *p_image };
313  let p_stream = unsafe { &mut *(p_stream as *mut opj_stream_private_t) };
314  let l_codec = &mut *(p_codec as *mut opj_codec_private_t);
315  l_codec.get_decoded_tile(p_stream, p_image, tile_index)
316}
317
318#[no_mangle]
319pub unsafe fn opj_set_decoded_resolution_factor(
320  mut p_codec: *mut opj_codec_t,
321  mut res_factor: OPJ_UINT32,
322) -> OPJ_BOOL {
323  if p_codec.is_null() {
324    return 0i32;
325  }
326  let l_codec = &mut *(p_codec as *mut opj_codec_private_t);
327  l_codec.set_decoded_resolution_factor(res_factor)
328}
329
330/* default decoding parameters */
331/* ---------------------------------------------------------------------- */
332/* COMPRESSION FUNCTIONS*/
333#[no_mangle]
334pub unsafe fn opj_create_compress(mut p_format: OPJ_CODEC_FORMAT) -> *mut opj_codec_t {
335  if let Some(codec) = opj_codec_private_t::new_encoder(p_format) {
336    let l_codec = Box::new(codec);
337    Box::into_raw(l_codec) as *mut opj_codec_t
338  } else {
339    core::ptr::null_mut()
340  }
341}
342
343/* default coding parameters */
344#[no_mangle]
345pub unsafe fn opj_set_default_encoder_parameters(mut parameters: *mut opj_cparameters_t) {
346  if parameters.is_null() {
347    return;
348  }
349  unsafe {
350    parameters.write_bytes(0, 1);
351  }
352  let parameters = &mut *parameters;
353  parameters.set_defaults();
354}
355
356#[no_mangle]
357pub unsafe fn opj_setup_encoder(
358  mut p_codec: *mut opj_codec_t,
359  mut parameters: *mut opj_cparameters_t,
360  mut p_image: *mut opj_image_t,
361) -> OPJ_BOOL {
362  if p_codec.is_null() | parameters.is_null() | p_image.is_null() {
363    return 0i32;
364  }
365  let p_image = unsafe { &mut *p_image };
366  let l_codec = &mut *(p_codec as *mut opj_codec_private_t);
367  let parameters = &mut *parameters;
368  l_codec.setup_encoder(parameters, p_image)
369}
370
371/* ----------------------------------------------------------------------- */
372#[no_mangle]
373pub unsafe fn opj_encoder_set_extra_options(
374  mut p_codec: *mut opj_codec_t,
375  mut options: *const *const core::ffi::c_char,
376) -> OPJ_BOOL {
377  if options.is_null() {
378    return 1;
379  }
380  if p_codec.is_null() {
381    return 0;
382  }
383  let l_codec = &mut *(p_codec as *mut opj_codec_private_t);
384  let mut p_option_iter = options;
385  let mut options = Vec::new();
386  while !(*p_option_iter).is_null() {
387    match core::ffi::CStr::from_ptr(*p_option_iter).to_str() {
388      Ok(option) => {
389        options.push(option);
390      }
391      Err(err) => {
392        log::error!("Failed to convert C string to Rust string: {err}");
393        return 0;
394      }
395    }
396    p_option_iter = p_option_iter.offset(1);
397  }
398  l_codec.encoder_set_extra_options(options.as_slice()) as _
399}
400
401/* ----------------------------------------------------------------------- */
402#[no_mangle]
403pub unsafe fn opj_start_compress(
404  mut p_codec: *mut opj_codec_t,
405  mut p_image: *mut opj_image_t,
406  mut p_stream: *mut opj_stream_t,
407) -> OPJ_BOOL {
408  if p_codec.is_null() | p_stream.is_null() | p_image.is_null() {
409    return 0i32;
410  }
411  let p_image = unsafe { &mut *p_image };
412  let p_stream = unsafe { &mut *(p_stream as *mut opj_stream_private_t) };
413  let l_codec = &mut *(p_codec as *mut opj_codec_private_t);
414  l_codec.start_compress(p_image, p_stream)
415}
416
417#[no_mangle]
418pub unsafe fn opj_encode(
419  mut p_codec: *mut opj_codec_t,
420  mut p_stream: *mut opj_stream_t,
421) -> OPJ_BOOL {
422  if p_codec.is_null() | p_stream.is_null() {
423    return 0i32;
424  }
425  let p_stream = unsafe { &mut *(p_stream as *mut opj_stream_private_t) };
426  let l_codec = &mut *(p_codec as *mut opj_codec_private_t);
427  l_codec.encode(p_stream)
428}
429
430#[no_mangle]
431pub unsafe fn opj_end_compress(
432  mut p_codec: *mut opj_codec_t,
433  mut p_stream: *mut opj_stream_t,
434) -> OPJ_BOOL {
435  if p_codec.is_null() | p_stream.is_null() {
436    return 0i32;
437  }
438  let p_stream = unsafe { &mut *(p_stream as *mut opj_stream_private_t) };
439  let l_codec = &mut *(p_codec as *mut opj_codec_private_t);
440  l_codec.end_compress(p_stream)
441}
442
443#[no_mangle]
444pub unsafe fn opj_end_decompress(
445  mut p_codec: *mut opj_codec_t,
446  mut p_stream: *mut opj_stream_t,
447) -> OPJ_BOOL {
448  if p_codec.is_null() | p_stream.is_null() {
449    return 0i32;
450  }
451  let p_stream = unsafe { &mut *(p_stream as *mut opj_stream_private_t) };
452  let l_codec = &mut *(p_codec as *mut opj_codec_private_t);
453  l_codec.end_decompress(p_stream)
454}
455
456#[no_mangle]
457pub unsafe fn opj_set_MCT(
458  mut parameters: *mut opj_cparameters_t,
459  mut pEncodingMatrix: *mut OPJ_FLOAT32,
460  mut p_dc_shift: *mut OPJ_INT32,
461  mut nb_comps: OPJ_UINT32,
462) -> OPJ_BOOL {
463  let mut l_matrix_size = nb_comps * nb_comps;
464  let mut l_dc_shift_size = nb_comps;
465  let encoding_matrix =
466    unsafe { core::slice::from_raw_parts(pEncodingMatrix, l_matrix_size as usize) };
467  let dc_shift = unsafe { core::slice::from_raw_parts(p_dc_shift, l_dc_shift_size as usize) };
468  let parameters = &mut *parameters;
469  parameters.set_MCT(encoding_matrix, dc_shift, nb_comps) as _
470}
471
472#[no_mangle]
473pub unsafe fn opj_write_tile(
474  mut p_codec: *mut opj_codec_t,
475  mut p_tile_index: OPJ_UINT32,
476  mut p_data: *mut OPJ_BYTE,
477  mut p_data_size: OPJ_UINT32,
478  mut p_stream: *mut opj_stream_t,
479) -> OPJ_BOOL {
480  if p_codec.is_null() | p_stream.is_null() | p_data.is_null() {
481    return 0i32;
482  }
483  let p_stream = unsafe { &mut *(p_stream as *mut opj_stream_private_t) };
484  let l_codec = &mut *(p_codec as *mut opj_codec_private_t);
485  let p_data = unsafe { core::slice::from_raw_parts(p_data as *const u8, p_data_size as usize) };
486  l_codec.write_tile(p_tile_index, p_data, p_stream)
487}
488
489/* ---------------------------------------------------------------------- */
490#[no_mangle]
491pub unsafe fn opj_destroy_codec(mut p_codec: *mut opj_codec_t) {
492  if p_codec.is_null() {
493    return;
494  }
495  let _ = Box::from_raw(p_codec as *mut opj_codec_private_t);
496}
497
498/* ---------------------------------------------------------------------- */
499#[cfg(feature = "file-io")]
500#[no_mangle]
501pub unsafe fn opj_dump_codec(
502  mut p_codec: *mut opj_codec_t,
503  mut info_flag: OPJ_INT32,
504  mut output_stream: *mut FILE,
505) {
506  if p_codec.is_null() {
507    return;
508  }
509  let l_codec = &mut *(p_codec as *mut opj_codec_private_t);
510  l_codec.dump_codec(info_flag, output_stream)
511}
512
513#[no_mangle]
514pub unsafe fn opj_get_cstr_info(mut p_codec: *mut opj_codec_t) -> *mut opj_codestream_info_v2_t {
515  if p_codec.is_null() {
516    return core::ptr::null_mut::<opj_codestream_info_v2_t>();
517  }
518  let l_codec = &mut *(p_codec as *mut opj_codec_private_t);
519  l_codec.get_cstr_info()
520}
521
522#[no_mangle]
523pub unsafe fn opj_destroy_cstr_info(mut cstr_info: *mut *mut opj_codestream_info_v2_t) {
524  if !cstr_info.is_null() {
525    // TODO: use drop.
526    if !(**cstr_info).m_default_tile_info.tccp_info.is_null() {
527      opj_free((**cstr_info).m_default_tile_info.tccp_info as *mut core::ffi::c_void);
528    }
529    if !(**cstr_info).tile_info.is_null() {
530      opj_free((**cstr_info).tile_info as *mut core::ffi::c_void);
531    }
532    opj_free(*cstr_info as *mut core::ffi::c_void);
533    *cstr_info = core::ptr::null_mut::<opj_codestream_info_v2_t>()
534  };
535}
536
537#[no_mangle]
538pub unsafe fn opj_get_cstr_index(mut p_codec: *mut opj_codec_t) -> *mut opj_codestream_index_t {
539  if p_codec.is_null() {
540    return core::ptr::null_mut::<opj_codestream_index_t>();
541  }
542  let l_codec = &mut *(p_codec as *mut opj_codec_private_t);
543  l_codec.get_cstr_index()
544}
545
546#[no_mangle]
547pub unsafe fn opj_destroy_cstr_index(mut p_cstr_index: *mut *mut opj_codestream_index_t) {
548  if !(*p_cstr_index).is_null() {
549    // TODO: use drop.
550    j2k_destroy_cstr_index(*p_cstr_index);
551    *p_cstr_index = core::ptr::null_mut::<opj_codestream_index_t>()
552  };
553}
554
555#[no_mangle]
556pub unsafe extern "C" fn opj_stream_create(
557  mut p_buffer_size: OPJ_SIZE_T,
558  mut l_is_input: OPJ_BOOL,
559) -> *mut opj_stream_t {
560  let l_stream = Box::new(opj_stream_private::new_custom(
561    p_buffer_size,
562    l_is_input != 0,
563  ));
564  let p_stream = Box::into_raw(l_stream) as *mut opj_stream_t;
565  log::trace!("-- create stream: {:?}", p_stream);
566  p_stream
567}
568
569#[no_mangle]
570pub unsafe extern "C" fn opj_stream_default_create(mut l_is_input: OPJ_BOOL) -> *mut opj_stream_t {
571  opj_stream_create(0x100000 as OPJ_SIZE_T, l_is_input)
572}
573
574#[no_mangle]
575pub unsafe extern "C" fn opj_stream_destroy(mut p_stream: *mut opj_stream_t) {
576  if !p_stream.is_null() {
577    let _ = Box::from_raw(p_stream as *mut opj_stream_private_t);
578  }
579}
580
581#[no_mangle]
582pub unsafe extern "C" fn opj_stream_set_read_function(
583  mut p_stream: *mut opj_stream_t,
584  mut p_function: opj_stream_read_fn,
585) {
586  if p_stream.is_null() {
587    return;
588  }
589  let p_stream = unsafe { &mut *(p_stream as *mut opj_stream_private_t) };
590  if !p_stream.is_input() {
591    return;
592  }
593  if let Some(custom) = p_stream.as_custom() {
594    custom.set_read(p_function);
595  }
596}
597
598#[no_mangle]
599pub unsafe extern "C" fn opj_stream_set_seek_function(
600  mut p_stream: *mut opj_stream_t,
601  mut p_function: opj_stream_seek_fn,
602) {
603  if p_stream.is_null() {
604    return;
605  }
606  let p_stream = unsafe { &mut *(p_stream as *mut opj_stream_private_t) };
607  if let Some(custom) = p_stream.as_custom() {
608    custom.set_seek(p_function);
609  }
610}
611
612#[no_mangle]
613pub unsafe extern "C" fn opj_stream_set_write_function(
614  mut p_stream: *mut opj_stream_t,
615  mut p_function: opj_stream_write_fn,
616) {
617  if p_stream.is_null() {
618    return;
619  }
620  let p_stream = unsafe { &mut *(p_stream as *mut opj_stream_private_t) };
621  if p_stream.is_input() {
622    return;
623  }
624  if let Some(custom) = p_stream.as_custom() {
625    custom.set_write(p_function);
626  }
627}
628
629#[no_mangle]
630pub unsafe extern "C" fn opj_stream_set_skip_function(
631  mut p_stream: *mut opj_stream_t,
632  mut p_function: opj_stream_skip_fn,
633) {
634  if p_stream.is_null() {
635    return;
636  }
637  let p_stream = unsafe { &mut *(p_stream as *mut opj_stream_private_t) };
638  if let Some(custom) = p_stream.as_custom() {
639    custom.set_skip(p_function);
640  }
641}
642
643#[no_mangle]
644pub unsafe extern "C" fn opj_stream_set_user_data(
645  mut p_stream: *mut opj_stream_t,
646  mut p_data: *mut core::ffi::c_void,
647  mut p_function: opj_stream_free_user_data_fn,
648) {
649  if p_stream.is_null() {
650    return;
651  }
652  let p_stream = unsafe { &mut *(p_stream as *mut opj_stream_private_t) };
653  if let Some(custom) = p_stream.as_custom() {
654    custom.set_user_data(p_data, p_function);
655  }
656}
657
658#[no_mangle]
659pub unsafe extern "C" fn opj_stream_set_user_data_length(
660  mut p_stream: *mut opj_stream_t,
661  mut data_length: OPJ_UINT64,
662) {
663  if p_stream.is_null() {
664    return;
665  }
666  let p_stream = unsafe { &mut *(p_stream as *mut opj_stream_private_t) };
667  p_stream.set_stream_length(data_length);
668}
669
670#[cfg(feature = "file-io")]
671#[no_mangle]
672pub unsafe fn opj_stream_create_default_file_stream(
673  mut fname: *const core::ffi::c_char,
674  mut p_is_read_stream: OPJ_BOOL,
675) -> *mut opj_stream_t {
676  opj_stream_create_file_stream(fname, 0x100000 as OPJ_SIZE_T, p_is_read_stream)
677}
678
679#[cfg(feature = "file-io")]
680#[no_mangle]
681pub unsafe fn opj_stream_create_file_stream(
682  mut fname: *const core::ffi::c_char,
683  mut p_size: OPJ_SIZE_T,
684  mut p_is_read_stream: OPJ_BOOL,
685) -> *mut opj_stream_t {
686  if fname.is_null() {
687    return core::ptr::null_mut::<opj_stream_t>();
688  }
689  match core::ffi::CStr::from_ptr(fname).to_str() {
690    Ok(name) => {
691      let l_stream = Box::new(opj_stream_private::new_file(
692        name,
693        p_size,
694        p_is_read_stream != 0,
695      ));
696      Box::into_raw(l_stream) as *mut opj_stream_t
697    }
698    Err(err) => {
699      log::error!("Failed to convert C filename to Rust String: {err}");
700      return core::ptr::null_mut::<opj_stream_t>();
701    }
702  }
703}
704
705#[no_mangle]
706pub unsafe fn opj_image_data_alloc(mut size: OPJ_SIZE_T) -> *mut core::ffi::c_void {
707  /* printf("opj_image_data_alloc %p\n", ret); */
708  opj_malloc(size)
709}
710
711#[no_mangle]
712pub unsafe fn opj_image_data_free(mut ptr: *mut core::ffi::c_void) {
713  /* printf("opj_image_data_free %p\n", ptr); */
714  opj_free(ptr);
715}
716
717/* Stub implementation */
718#[no_mangle]
719pub fn opj_has_thread_support() -> OPJ_BOOL {
720  0i32
721}
722#[no_mangle]
723pub fn opj_get_num_cpus() -> core::ffi::c_int {
724  1i32
725}