#![allow(dead_code)]
#![allow(mutable_transmutes)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(non_upper_case_globals)]
#![allow(unused_assignments)]
#![allow(unused_mut)]
#![cfg_attr(not(feature = "std"), no_std)]
#[cfg(not(feature = "std"))]
#[macro_use]
extern crate alloc;
#[cfg(feature = "std")]
extern crate std as alloc;
#[cfg(feature = "file-io")]
extern crate libc;
#[cfg(not(feature = "std"))]
use alloc::string::String;
mod c_api_types;
mod consts;
mod types;
#[macro_use]
mod event;
#[cfg(feature = "file-io")]
#[macro_use]
mod fprintf;
pub mod image;
pub mod openjpeg;
pub mod stream;
pub use c_api_types::*;
pub use codec::Codec;
pub use image::{opj_image, opj_image_comptparm};
pub use types::{ICCProfile, ICCProfileMut, ICCProfileRef, Stream, TileInfo};
pub const JP2_RFC3745_MAGIC: &'static [u8] = &[
0x00, 0x00, 0x00, 0x0c, 0x6a, 0x50, 0x20, 0x20, 0x0d, 0x0a, 0x87, 0x0a,
];
pub const JP2_MAGIC: &'static [u8] = &[0x0d, 0x0a, 0x87, 0x0a];
pub const J2K_CODESTREAM_MAGIC: &'static [u8] = &[0xff, 0x4f, 0xff, 0x51];
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum J2KFormat {
JP2,
J2K,
JPT,
}
pub fn detect_format(buf: &[u8]) -> Result<J2KFormat, String> {
if buf.starts_with(JP2_RFC3745_MAGIC) {
Ok(J2KFormat::JP2)
} else if buf.starts_with(JP2_MAGIC) {
Ok(J2KFormat::JP2)
} else if buf.starts_with(J2K_CODESTREAM_MAGIC) {
Ok(J2KFormat::J2K)
} else {
Err("Can't detect image format from bytes".into())
}
}
pub fn detect_format_from_extension(ext: Option<&str>) -> Result<J2KFormat, String> {
let lower_ext = ext.map(|e| e.to_ascii_lowercase());
match lower_ext.as_deref() {
Some("jp2") => Ok(J2KFormat::JP2),
Some("jpt") => Ok(J2KFormat::JPT),
Some("j2k") | Some("j2c") | Some("jpc") => Ok(J2KFormat::J2K),
Some("jph") => Ok(J2KFormat::JP2),
Some("jhc") => Ok(J2KFormat::J2K),
Some(ext) => Err(format!("Unknown file extension: {}", ext)),
None => Err("No file extension".into()),
}
}
#[cfg(feature = "std")]
pub fn detect_format_from_extension_os_str(
ext: Option<&std::ffi::OsStr>,
) -> Result<J2KFormat, String> {
let ext = ext.map(|ext| ext.to_string_lossy());
detect_format_from_extension(ext.as_deref())
}
#[cfg(feature = "file-io")]
fn detect_from_file_magic<P: AsRef<std::path::Path>>(path: P) -> Result<J2KFormat, String> {
use alloc::io::Read;
let mut buf = [0; 12];
let mut file = std::fs::File::open(path).map_err(|e| e.to_string())?;
file.read_exact(&mut buf).map_err(|e| e.to_string())?;
detect_format(&buf)
}
#[cfg(feature = "file-io")]
pub fn detect_format_from_file<P: AsRef<std::path::Path>>(path: P) -> Result<J2KFormat, String> {
let path = path.as_ref();
let ext = path.extension().map(|ext| ext.to_string_lossy());
let ext_format = detect_format_from_extension(ext.as_deref())?;
if ext_format == J2KFormat::JPT {
return Ok(J2KFormat::JPT);
}
let Ok(magic_format) = detect_from_file_magic(path) else {
return Ok(ext_format);
};
if ext_format != magic_format {
eprintln!(
"Warning: File extension format ({:?}) doesn't match magic bytes format ({:?})",
ext_format, magic_format
);
}
Ok(magic_format)
}
mod bio;
mod cio;
mod codec;
mod dwt;
mod function_list;
mod ht_dec;
mod invert;
mod j2k;
mod jp2;
mod malloc;
mod math;
mod mct;
mod mqc;
mod pi;
mod sparse_array;
mod t1;
mod t1_ht_luts;
mod t1_luts;
mod t2;
mod tcd;
mod tgt;