1#![allow(clippy::needless_borrow)]
2#![allow(clippy::missing_safety_doc)]
3#![allow(non_upper_case_globals)]
4#![cfg_attr(not(feature = "c_ffi"), allow(deprecated))]
5
6#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
7mod libc;
8
9use crate::Error;
10use super::{ColorMode, ColorProfile, ColorType, CompressSettings, DecoderSettings, DecompressSettings, EncoderSettings, ErrorCode, Info, State};
11use crate::ChunkRef;
12use crate::rustimpl::RGBA;
13use crate::rustimpl;
14use crate::zlib;
15use std::path::Path;
16use std::ffi::CStr;
17use std::io::Read;
18use std::io::Write;
19use std::mem;
20use std::os::raw::{c_char, c_long, c_uint, c_void};
21use std::ptr;
22use std::slice;
23
24macro_rules! lode_error {
25 ($e:expr) => {
26 if let Err(e) = $e {
27 ErrorCode::from(e)
28 } else {
29 ErrorCode(0)
30 }
31 };
32}
33
34macro_rules! lode_try {
35 ($e:expr) => {{
36 match $e {
37 Err(e) => return ErrorCode::from(e),
38 Ok(o) => o,
39 }
40 }};
41}
42
43macro_rules! lode_try_state {
44 ($state:expr, $e:expr) => {{
45 match $e {
46 Err(err) => {
47 $state = ErrorCode::from(err);
48 return ErrorCode::from(err);
49 },
50 Ok(ok) => {
51 $state = ErrorCode(0);
52 ok
53 }
54 }
55 }};
56}
57
58unsafe fn vec_from_raw(data: *mut u8, len: usize) -> Vec<u8> {
59 if data.is_null() || 0 == len {
60 return Vec::new();
61 }
62 slice::from_raw_parts_mut(data, len).to_owned()
63}
64
65fn vec_into_raw(v: Vec<u8>) -> Result<(*mut u8, usize), crate::Error> {
66 unsafe {
67 let len = v.len();
68 let data = lodepng_malloc(len).cast::<u8>();
69 if data.is_null() {
70 Err(crate::Error::new(83))
71 } else {
72 slice::from_raw_parts_mut(data, len).clone_from_slice(&v);
73 Ok((data, len))
74 }
75 }
76}
77
78
79#[no_mangle]
80#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
81pub unsafe extern "C" fn lodepng_malloc(size: usize) -> *mut c_void {
82 libc::malloc(size)
83}
84
85#[no_mangle]
86#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
87pub unsafe extern "C" fn lodepng_realloc(ptr: *mut c_void, size: usize) -> *mut c_void {
88 libc::realloc(ptr, size)
89}
90
91#[no_mangle]
92#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
93pub unsafe extern "C" fn lodepng_free(ptr: *mut c_void) {
94 libc::free(ptr);
95}
96
97#[no_mangle]
98#[allow(deprecated)]
99#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
100pub unsafe extern "C" fn lodepng_state_init(state: *mut State) {
101 ptr::write(state, State::new());
102}
103
104#[no_mangle]
105#[allow(deprecated)]
106#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
107pub unsafe extern "C" fn lodepng_state_cleanup(state: &mut State) {
108 *state = State::new();
110}
111
112#[no_mangle]
113#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
114pub unsafe extern "C" fn lodepng_state_copy(dest: *mut State, source: &State) -> ErrorCode {
115 ptr::write(dest, source.clone());
116 ErrorCode(0)
117}
118
119#[no_mangle]
120#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
121pub unsafe extern "C" fn lodepng_error_text(code: ErrorCode) -> *const u8 {
122 code.c_description().as_ptr()
123}
124
125#[no_mangle]
126#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
127pub unsafe extern "C" fn lodepng_encode32(out: &mut *mut u8, outsize: &mut usize, image: *const u8, w: c_uint, h: c_uint) -> ErrorCode {
128 if image.is_null() {
129 return ErrorCode(48);
130 }
131 try_vec_into_raw(out, outsize, rustimpl::lodepng_encode_memory(slice::from_raw_parts(image, 0x1FFF_FFFF), w, h, ColorType::RGBA, 8))
132}
133
134#[no_mangle]
135#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
136pub unsafe extern "C" fn lodepng_encode24(out: &mut *mut u8, outsize: &mut usize, image: *const u8, w: c_uint, h: c_uint) -> ErrorCode {
137 if image.is_null() {
138 return ErrorCode(48);
139 }
140 try_vec_into_raw(out, outsize, rustimpl::lodepng_encode_memory(slice::from_raw_parts(image, 0x1FFF_FFFF), w, h, ColorType::RGB, 8))
141}
142
143#[inline]
144fn load_file(filename: &Path) -> Result<Vec<u8>, Error> {
145 std::fs::read(filename).map_err(|_| Error::new(78))
146}
147
148fn save_file(buffer: &[u8], filename: &Path) -> Result<(), Error> {
150 std::fs::write(filename, buffer)
151 .map_err(|_| Error::new(79))
152}
153
154#[inline]
155fn encode_file(filename: &Path, image: &[u8], w: u32, h: u32, colortype: ColorType, bitdepth: u32) -> Result<(), Error> {
156 let v = rustimpl::lodepng_encode_memory(image, w, h, colortype, bitdepth)?;
157 save_file(&v, filename)
158}
159
160#[no_mangle]
161#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
162pub unsafe extern "C" fn lodepng_encode_file(filename: *const c_char, image: *const u8, w: c_uint, h: c_uint, colortype: ColorType, bitdepth: c_uint) -> ErrorCode {
163 if image.is_null() {
164 return ErrorCode(48);
165 }
166 lode_error!(encode_file(&c_path(filename), slice::from_raw_parts(image, 0x1FFF_FFFF), w, h, colortype, bitdepth))
167}
168
169#[no_mangle]
170#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
171pub unsafe extern "C" fn lodepng_encode32_file(filename: *const c_char, image: *const u8, w: c_uint, h: c_uint) -> ErrorCode {
172 if image.is_null() {
173 return ErrorCode(48);
174 }
175 lode_error!(encode_file(&c_path(filename), slice::from_raw_parts(image, 0x1FFF_FFFF), w, h, ColorType::RGBA, 8))
176}
177
178#[no_mangle]
179#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
180pub unsafe extern "C" fn lodepng_encode24_file(filename: *const c_char, image: *const u8, w: c_uint, h: c_uint) -> ErrorCode {
181 if image.is_null() {
182 return ErrorCode(48);
183 }
184 lode_error!(encode_file(&c_path(filename), slice::from_raw_parts(image, 0x1FFF_FFFF), w, h, ColorType::RGB, 8))
185}
186
187#[no_mangle]
188#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
189pub unsafe extern "C" fn lodepng_get_bpp_lct(colortype: ColorType, bitdepth: c_uint) -> c_uint {
190 colortype.bpp(bitdepth) as _
191}
192
193#[no_mangle]
194#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
195pub unsafe extern "C" fn lodepng_get_bpp(info: &ColorMode) -> c_uint {
196 info.bpp()
197}
198
199#[no_mangle]
200#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
201pub unsafe extern "C" fn lodepng_get_channels(info: &ColorMode) -> c_uint {
202 c_uint::from(info.channels())
203}
204
205#[no_mangle]
206#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
207pub unsafe extern "C" fn lodepng_is_greyscale_type(info: &ColorMode) -> c_uint {
208 c_uint::from(info.is_greyscale_type())
209}
210
211#[no_mangle]
212#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
213pub unsafe extern "C" fn lodepng_is_alpha_type(info: &ColorMode) -> c_uint {
214 c_uint::from(info.is_alpha_type())
215}
216
217#[no_mangle]
218#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
219pub unsafe extern "C" fn lodepng_is_palette_type(info: &ColorMode) -> c_uint {
220 c_uint::from(info.is_palette_type())
221}
222
223#[no_mangle]
224#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
225pub unsafe extern "C" fn lodepng_has_palette_alpha(info: &ColorMode) -> c_uint {
226 c_uint::from(info.has_palette_alpha())
227}
228
229#[no_mangle]
230#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
231pub unsafe extern "C" fn lodepng_can_have_alpha(info: &ColorMode) -> c_uint {
232 c_uint::from(info.can_have_alpha())
233}
234
235#[no_mangle]
236#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
237pub unsafe extern "C" fn lodepng_get_raw_size(w: c_uint, h: c_uint, color: &ColorMode) -> usize {
238 color.raw_size(w, h)
239}
240
241fn get_raw_size_lct(w: u32, h: u32, colortype: ColorType, bitdepth: u32) -> usize {
242 let bpp = colortype.bpp(bitdepth) as usize;
244 let n = w as usize * h as usize;
245 ((n / 8) * bpp) + ((n & 7) * bpp + 7) / 8
246}
247
248#[no_mangle]
249#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
250pub unsafe extern "C" fn lodepng_get_raw_size_lct(w: c_uint, h: c_uint, colortype: ColorType, bitdepth: c_uint) -> usize {
251 get_raw_size_lct(w, h, colortype, bitdepth)
252}
253
254#[no_mangle]
255#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
256pub unsafe extern "C" fn lodepng_palette_clear(info: &mut ColorMode) {
257 info.palette_clear();
258}
259
260#[no_mangle]
261#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
262pub unsafe extern "C" fn lodepng_palette_add(info: &mut ColorMode, r: u8, g: u8, b: u8, a: u8) -> ErrorCode {
263 lode_error!(info.palette_add(RGBA { r, g, b, a }))
264}
265
266#[no_mangle]
267#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
268pub unsafe extern "C" fn lodepng_clear_text(info: &mut Info) {
269 info.clear_text();
270}
271
272#[no_mangle]
273#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
274pub unsafe extern "C" fn lodepng_add_text(info: &mut Info, key: *const c_char, str: *const c_char) -> ErrorCode {
275 let k = lode_try!(CStr::from_ptr(key).to_str().map_err(|_| ErrorCode(89)));
276 let s = lode_try!(CStr::from_ptr(str).to_str().map_err(|_| ErrorCode(89)));
277 lode_error!(info.add_text(k, s))
278}
279
280#[no_mangle]
281#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
282pub unsafe extern "C" fn lodepng_clear_itext(info: &mut Info) {
283 info.clear_itext();
284}
285
286#[no_mangle]
287#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
288pub unsafe extern "C" fn lodepng_add_itext(info: &mut Info, key: *const c_char, langtag: *const c_char, transkey: *const c_char, str: *const c_char) -> ErrorCode {
289 let k = CStr::from_ptr(key);
290 let l = CStr::from_ptr(langtag);
291 let t = CStr::from_ptr(transkey);
292 let s = CStr::from_ptr(str);
293 lode_error!(info.push_itext(k.to_bytes(), l.to_bytes(), t.to_bytes(), s.to_bytes()))
294}
295
296#[no_mangle]
298#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
299pub unsafe extern "C" fn lodepng_chunk_create(out: &mut *mut u8, outsize: &mut usize, length: c_uint, type_: *const [u8; 4], data: *const u8) -> ErrorCode {
300 let data = slice::from_raw_parts(data, length as usize);
301 let type_ = type_.as_ref().unwrap();
302
303 if *outsize == 0 && !(*out).is_null() {
305 let vec = std::mem::transmute::<&mut *mut u8, &mut &mut Vec<u8>>(out);
306 let mut ch = rustimpl::ChunkBuilder::new(vec, type_);
307 lode_try!(ch.extend_from_slice(data));
308 lode_error!(ch.finish())
309 } else {
310 let mut v = vec_from_raw(*out, *outsize);
311 let mut ch = rustimpl::ChunkBuilder::new(&mut v, type_);
312 lode_try!(ch.extend_from_slice(data));
313 let err = lode_error!(ch.finish());
314 let (data, size) = lode_try!(vec_into_raw(v));
315 *out = data;
316 *outsize = size;
317 err
318 }
319}
320
321#[no_mangle]
322#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
323pub unsafe extern "C" fn lodepng_chunk_length(chunk: *const u8) -> c_uint {
324 rustimpl::chunk_length(slice::from_raw_parts(chunk, 12)) as c_uint
325}
326
327#[no_mangle]
328#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
329pub unsafe extern "C" fn lodepng_chunk_type(type_: &mut [u8; 5], chunk: *const u8) {
330 let ch = ChunkRef::from_ptr(chunk).unwrap();
331 let t = ch.name();
332 type_[0..4].clone_from_slice(&t);
333 type_[4] = 0;
334}
335
336#[no_mangle]
337#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
338pub unsafe extern "C" fn lodepng_chunk_type_equals(chunk: *const u8, name: &[u8; 4]) -> u8 {
339 if name.contains(&0) {
340 return 0;
341 }
342 let ch = ChunkRef::from_ptr(chunk).unwrap();
343 u8::from(name == &ch.name())
344}
345
346#[no_mangle]
347#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
348pub unsafe extern "C" fn lodepng_chunk_data_const(chunk: *const u8) -> *const u8 {
349 ChunkRef::from_ptr(chunk).unwrap().data().as_ptr()
350}
351
352#[no_mangle]
353#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
354pub unsafe extern "C" fn lodepng_chunk_next(chunk: *mut u8) -> *mut u8 {
355 let len = lodepng_chunk_length(chunk) as usize;
356 chunk.add(len + 12)
357}
358
359#[no_mangle]
360#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
361pub unsafe extern "C" fn lodepng_chunk_next_const(chunk: *const u8) -> *const u8 {
362 let len = lodepng_chunk_length(chunk) as usize;
363 chunk.add(len + 12)
364}
365
366#[no_mangle]
367#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
368pub unsafe extern "C" fn lodepng_chunk_ancillary(chunk: *const u8) -> u8 {
369 u8::from(ChunkRef::from_ptr(chunk).unwrap().is_ancillary())
370}
371
372#[no_mangle]
373#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
374pub unsafe extern "C" fn lodepng_chunk_private(chunk: *const u8) -> u8 {
375 u8::from(ChunkRef::from_ptr(chunk).unwrap().is_private())
376}
377
378#[no_mangle]
379#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
380pub unsafe extern "C" fn lodepng_chunk_safetocopy(chunk: *const u8) -> u8 {
381 u8::from(ChunkRef::from_ptr(chunk).unwrap().is_safe_to_copy())
382}
383
384#[no_mangle]
385#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
386pub unsafe extern "C" fn lodepng_chunk_data(chunk_data: *mut u8) -> *mut u8 {
387 chunk_data.add(8)
388}
389
390#[no_mangle]
391#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
392pub unsafe extern "C" fn lodepng_chunk_check_crc(chunk: *const u8) -> c_uint {
393 c_uint::from(ChunkRef::from_ptr(chunk).unwrap().check_crc())
394}
395
396#[no_mangle]
397#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
398pub unsafe extern "C" fn lodepng_chunk_generate_crc(chunk: *mut u8) {
399 rustimpl::lodepng_chunk_generate_crc(slice::from_raw_parts_mut(chunk, 0x7FFF_FFFF));
400}
401
402#[no_mangle]
403#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
404pub unsafe extern "C" fn lodepng_chunk_append(out: &mut *mut u8, outsize: &mut usize, chunk: *const u8) -> ErrorCode {
405 let mut v = vec_from_raw(*out, *outsize);
406 lode_try!(chunk_append(&mut v, slice::from_raw_parts(chunk, 0x7FFF_FFFF)));
407 let (data, size) = lode_try!(vec_into_raw(v));
408 *out = data;
409 *outsize = size;
410 ErrorCode(0)
411}
412#[inline]
413fn chunk_append(out: &mut Vec<u8>, chunk: &[u8]) -> Result<(), crate::Error> {
414 let total_chunk_length = rustimpl::chunk_length(chunk) + 12;
415 out.try_reserve(total_chunk_length)?;
416 out.extend_from_slice(&chunk[0..total_chunk_length]);
417 Ok(())
418}
419
420#[no_mangle]
421#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
422pub unsafe extern "C" fn lodepng_color_mode_init(info: *mut ColorMode) {
423 ptr::write(info, ColorMode::new());
424}
425
426#[no_mangle]
427#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
428pub unsafe extern "C" fn lodepng_color_mode_cleanup(info: &mut ColorMode) {
429 let mut hack = mem::zeroed();
430 ptr::swap(&mut hack, info);
431}
432
433#[no_mangle]
434#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
435pub unsafe extern "C" fn lodepng_color_mode_equal(a: &ColorMode, b: &ColorMode) -> c_uint {
436 c_uint::from(rustimpl::lodepng_color_mode_equal(a, b))
437}
438
439#[no_mangle]
440#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
441pub unsafe extern "C" fn lodepng_color_mode_copy(dest: *mut ColorMode, source: &ColorMode) -> ErrorCode {
442 ptr::write(dest, source.clone());
443 ErrorCode(0)
444}
445
446#[no_mangle]
447#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
448pub unsafe extern "C" fn lodepng_zlib_decompress(out: &mut *mut u8, outsize: &mut usize, inp: *const u8, insize: usize, settings: &DecompressSettings) -> ErrorCode {
449 *out = ptr::null_mut();
450 *outsize = 0;
451 let inp = if !inp.is_null() {
452 slice::from_raw_parts(inp, insize)
453 } else if insize != 0 {
454 return ErrorCode(48);
455 } else {
456 &[][..]
457 };
458 let vec = lode_try!(zlib::decompress(inp, settings));
459 try_vec_into_raw(out, outsize, Ok(vec))
460}
461
462#[no_mangle]
463#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
464pub unsafe extern "C" fn zlib_decompress(out: &mut *mut u8, outsize: &mut usize, inp: *const u8, insize: usize, settings: &DecompressSettings) -> ErrorCode {
465 let inp = if !inp.is_null() {
466 slice::from_raw_parts(inp, insize)
467 } else if insize != 0 {
468 return ErrorCode(48);
469 } else {
470 &[][..]
471 };
472 try_vec_into_raw(out, outsize, zlib::decompress(inp, settings))
473}
474
475#[no_mangle]
477#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
478pub unsafe extern "C" fn lodepng_zlib_compress(out: &mut *mut u8, outsize: &mut usize, inp: *const u8, insize: usize, settings: &CompressSettings) -> ErrorCode {
479 let inp = if !inp.is_null() {
480 slice::from_raw_parts(inp, insize)
481 } else if insize != 0 {
482 return ErrorCode(48);
483 } else {
484 &[][..]
485 };
486 let mut v = vec_from_raw(*out, *outsize);
487 let mut z = zlib::new_compressor(&mut v, settings);
488 let err = lode_error!(z.write_all(inp).map_err(Error::from));
489 drop(z);
490 let (data, size) = lode_try!(vec_into_raw(v));
491 *out = data;
492 *outsize = size;
493 err
494}
495
496#[no_mangle]
497#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
498pub unsafe extern "C" fn zlib_compress(out: &mut *mut u8, outsize: &mut usize, inp: *const u8, insize: usize, settings: &CompressSettings) -> ErrorCode {
499 let inp = if !inp.is_null() {
500 slice::from_raw_parts(inp, insize)
501 } else if insize != 0 {
502 return ErrorCode(48);
503 } else {
504 &[][..]
505 };
506 let mut vec = Vec::new();
507 let _ = vec.try_reserve(inp.len() / 2);
508 let res = zlib::compress_into(&mut vec, inp, settings);
509 try_vec_into_raw(out, outsize, res.map(move |()| vec))
510}
511
512#[no_mangle]
513#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
514pub unsafe extern "C" fn lodepng_compress_settings_init(settings: *mut CompressSettings) {
515 ptr::write(settings, CompressSettings::new());
516}
517
518#[no_mangle]
519#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
520pub unsafe extern "C" fn lodepng_decompress_settings_init(settings: *mut DecompressSettings) {
521 ptr::write(settings, DecompressSettings::new());
522}
523
524#[no_mangle]
525#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
526pub unsafe extern "C" fn lodepng_crc32(data: *const u8, length: usize) -> c_uint {
527 if data.is_null() {
528 return 0;
529 }
530 crc32fast::hash(slice::from_raw_parts(data, length))
531}
532
533#[no_mangle]
534#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
535pub unsafe extern "C" fn lodepng_info_init(info: *mut Info) {
536 ptr::write(info, Info::new());
537}
538
539#[no_mangle]
540#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
541pub unsafe extern "C" fn lodepng_info_cleanup(info: &mut Info) {
542 *info = Info::new();
544}
545
546#[no_mangle]
547#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
548pub unsafe extern "C" fn lodepng_info_copy(dest: *mut Info, source: &Info) -> ErrorCode {
549 ptr::write(dest, source.clone());
550 ErrorCode(0)
551}
552
553#[no_mangle]
554#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
555pub unsafe extern "C" fn lodepng_info_swap(a: &mut Info, b: &mut Info) {
556 mem::swap(a, b);
557}
558
559#[no_mangle]
560#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
561pub unsafe extern "C" fn lodepng_convert(out: *mut u8, image: *const u8, mode_out: &ColorMode, mode_in: &ColorMode, w: c_uint, h: c_uint) -> ErrorCode {
562 if image.is_null() {
563 return ErrorCode(48);
564 }
565 lode_error!(rustimpl::lodepng_convert(slice::from_raw_parts_mut(out, 0x1FFF_FFFF), slice::from_raw_parts(image, 0x1FFF_FFFF), mode_out, mode_in, w, h))
566}
567
568#[no_mangle]
569#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
570pub unsafe extern "C" fn lodepng_inspect(w_out: &mut c_uint, h_out: &mut c_uint, state: &mut State, inp: *const u8, insize: usize) -> ErrorCode {
571 if inp.is_null() {
572 return ErrorCode(48);
573 }
574 let (info, w, h) = lode_try_state!(state.error, rustimpl::lodepng_inspect(&state.decoder, slice::from_raw_parts(inp, insize), false));
575 state.info_png = info;
576 *w_out = w as c_uint;
577 *h_out = h as c_uint;
578 ErrorCode(0)
579}
580
581#[no_mangle]
582#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
583pub unsafe extern "C" fn lodepng_decode(out: &mut *mut u8, w_out: &mut c_uint, h_out: &mut c_uint, state: &mut State, inp: *const u8, insize: usize) -> ErrorCode {
584 if inp.is_null() || insize == 0 {
585 return ErrorCode(48);
586 }
587 *out = ptr::null_mut();
588 let (v, w, h) = lode_try_state!(state.error, rustimpl::lodepng_decode(state, slice::from_raw_parts(inp, insize)));
589 *w_out = w;
590 *h_out = h;
591 let (data, _) = lode_try!(vec_into_raw(v));
592 *out = data;
593 ErrorCode(0)
594}
595
596#[no_mangle]
597#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
598pub unsafe extern "C" fn lodepng_decode_memory(out: &mut *mut u8, w_out: &mut c_uint, h_out: &mut c_uint, inp: *const u8, insize: usize, colortype: ColorType, bitdepth: c_uint) -> ErrorCode {
599 *out = ptr::null_mut();
600 if inp.is_null() || insize == 0 {
601 return ErrorCode(48);
602 }
603 let (v, w, h) = lode_try!(rustimpl::lodepng_decode_memory(slice::from_raw_parts(inp, insize), colortype, bitdepth));
604 *w_out = w;
605 *h_out = h;
606 let (data, _) = lode_try!(vec_into_raw(v));
607 *out = data;
608 ErrorCode(0)
609}
610
611#[no_mangle]
612#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
613pub unsafe extern "C" fn lodepng_decode32(out: &mut *mut u8, w: &mut c_uint, h: &mut c_uint, inp: *const u8, insize: usize) -> ErrorCode {
614 lodepng_decode_memory(out, w, h, inp, insize, ColorType::RGBA, 8)
615}
616
617#[no_mangle]
618#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
619pub unsafe extern "C" fn lodepng_decode24(out: &mut *mut u8, w: &mut c_uint, h: &mut c_uint, inp: *const u8, insize: usize) -> ErrorCode {
620 lodepng_decode_memory(out, w, h, inp, insize, ColorType::RGB, 8)
621}
622
623#[inline]
624fn decode_file(filename: &Path, colortype: ColorType, bitdepth: u32) -> Result<(Vec<u8>, u32, u32), Error> {
625 let buf = load_file(filename)?;
626 rustimpl::lodepng_decode_memory(&buf, colortype, bitdepth)
627}
628
629#[no_mangle]
630#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
631pub unsafe extern "C" fn lodepng_decode_file(out: &mut *mut u8, w_out: &mut c_uint, h_out: &mut c_uint, filename: *const c_char, colortype: ColorType, bitdepth: c_uint) -> ErrorCode {
632 *out = ptr::null_mut();
633 let (v, w, h) = lode_try!(decode_file(&c_path(filename), colortype, bitdepth));
634 *w_out = w;
635 *h_out = h;
636 let (data, _) = lode_try!(vec_into_raw(v));
637 *out = data;
638 ErrorCode(0)
639}
640
641#[no_mangle]
642#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
643pub unsafe extern "C" fn lodepng_decode32_file(out: &mut *mut u8, w: &mut c_uint, h: &mut c_uint, filename: *const c_char) -> ErrorCode {
644 lodepng_decode_file(out, w, h, filename, ColorType::RGBA, 8)
645}
646
647#[no_mangle]
648#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
649pub unsafe extern "C" fn lodepng_decode24_file(out: &mut *mut u8, w: &mut c_uint, h: &mut c_uint, filename: *const c_char) -> ErrorCode {
650 lodepng_decode_file(out, w, h, filename, ColorType::RGB, 8)
651}
652
653#[no_mangle]
654#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
655pub unsafe extern "C" fn lodepng_decoder_settings_init(settings: *mut DecoderSettings) {
656 ptr::write(settings, DecoderSettings::new());
657}
658
659#[no_mangle]
660#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
661pub unsafe extern "C" fn lodepng_buffer_file(out: *mut u8, size: usize, filename: *const c_char) -> ErrorCode {
662 let out = slice::from_raw_parts_mut(out, size);
663 let res = std::fs::File::open(c_path(filename))
664 .and_then(|mut f| f.read_exact(out))
665 .map_err(|_| crate::Error::new(78));
666 lode_error!(res)
667}
668
669#[no_mangle]
670#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
671pub unsafe extern "C" fn lodepng_load_file(out: &mut *mut u8, outsize: &mut usize, filename: *const c_char) -> ErrorCode {
672 try_vec_into_raw(out, outsize, load_file(&c_path(filename)))
673}
674
675#[no_mangle]
676#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
677pub unsafe extern "C" fn lodepng_save_file(buffer: *const u8, buffersize: usize, filename: *const c_char) -> ErrorCode {
678 if buffer.is_null() {
679 return ErrorCode(48);
680 }
681 lode_error!(save_file(slice::from_raw_parts(buffer, buffersize), &c_path(filename)))
682}
683
684#[no_mangle]
685#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
686pub unsafe extern "C" fn lodepng_encode(out: &mut *mut u8, outsize: &mut usize, image: *const u8, w: c_uint, h: c_uint, state: &mut State) -> ErrorCode {
687 *out = ptr::null_mut();
688 *outsize = 0;
689 if image.is_null() {
690 return ErrorCode(48);
691 }
692 let res = lode_try_state!(state.error, rustimpl::lodepng_encode(slice::from_raw_parts(image, 0x1FFF_FFFF), w as _, h as _, state));
693 let (data, size) = lode_try!(vec_into_raw(res));
694 *out = data;
695 *outsize = size;
696 ErrorCode(0)
697}
698
699#[no_mangle]
700#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
701pub unsafe extern "C" fn lodepng_get_color_profile(profile_out: *mut ColorProfile, image: *const u8, w: c_uint, h: c_uint, mode: &ColorMode) -> ErrorCode {
702 if image.is_null() {
703 return ErrorCode(48);
704 }
705 let prof = rustimpl::get_color_profile(slice::from_raw_parts(image, 0x1FFF_FFFF), w, h, mode);
706 ptr::write(profile_out, prof);
707 ErrorCode(0)
708}
709
710#[no_mangle]
711#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
712pub unsafe extern "C" fn lodepng_auto_choose_color(mode_out: &mut ColorMode, image: *const u8, w: c_uint, h: c_uint, mode_in: &ColorMode) -> ErrorCode {
713 if image.is_null() {
714 return ErrorCode(48);
715 }
716 let mode = lode_try!(rustimpl::auto_choose_color(slice::from_raw_parts(image, 0x1FFF_FFFF), w as _, h as _, mode_in));
717 ptr::write(mode_out, mode);
718 ErrorCode(0)
719}
720
721#[no_mangle]
722#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
723pub unsafe extern "C" fn lodepng_filesize(filename: *const c_char) -> c_long {
724 std::fs::metadata(c_path(filename)).map(|m| m.len()).ok()
725 .map_or(-1, |l| l as c_long)
726}
727
728#[no_mangle]
729#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
730pub unsafe extern "C" fn lodepng_encode_memory(out: &mut *mut u8, outsize: &mut usize, image: *const u8, w: c_uint, h: c_uint, colortype: ColorType, bitdepth: c_uint) -> ErrorCode {
731 if image.is_null() {
732 return ErrorCode(48);
733 }
734 try_vec_into_raw(out, outsize, rustimpl::lodepng_encode_memory(slice::from_raw_parts(image, 0x1FFF_FFFF), w, h, colortype, bitdepth))
735}
736
737#[no_mangle]
738#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
739pub unsafe extern "C" fn lodepng_encoder_settings_init(settings: *mut EncoderSettings) {
740 ptr::write(settings, EncoderSettings::new());
741}
742
743#[no_mangle]
744#[cfg_attr(not(feature = "c_ffi"), deprecated(note = "enable c_ffi feature in lodepng to use the C API"))]
745pub unsafe extern "C" fn lodepng_color_profile_init(prof: *mut ColorProfile) {
746 ptr::write(prof, ColorProfile::new());
747}
748
749#[no_mangle]
750#[allow(deprecated)]
751pub static lodepng_default_compress_settings: CompressSettings = CompressSettings {
752 btype: 0,
753 use_lz77: true,
754 windowsize: 0,
755 minmatch: 0,
756 nicematch: 0,
757 lazymatching: false,
758 custom_zlib: None,
759 custom_deflate: None,
760 custom_context: 0usize as *mut _,
761};
762
763#[no_mangle]
764pub static lodepng_default_decompress_settings: DecompressSettings = DecompressSettings {
765 custom_zlib: None,
766 custom_inflate: None,
767 custom_context: 0usize as *mut _,
768};
769
770#[cfg(unix)]
771unsafe fn c_path<'meh>(filename: *const c_char) -> &'meh std::path::Path {
772 use std::ffi::OsStr;
773 use std::os::unix::ffi::OsStrExt;
774 assert!(!filename.is_null());
775 let tmp = CStr::from_ptr(filename);
776 std::path::Path::new(OsStr::from_bytes(tmp.to_bytes()))
777}
778
779#[cfg(not(unix))]
780unsafe fn c_path(filename: *const c_char) -> std::path::PathBuf {
781 let tmp = CStr::from_ptr(filename);
782 tmp.to_string_lossy().to_string().into()
783}
784
785#[inline]
786unsafe fn try_vec_into_raw(out: &mut *mut u8, outsize: &mut usize, result: Result<Vec<u8>, crate::Error>) -> ErrorCode {
787 match result.and_then(vec_into_raw) {
788 Ok((data, len)) => {
789 *out = data;
790 *outsize = len;
791 ErrorCode(0)
792 },
793 Err(err) => {
794 *out = ptr::null_mut();
795 *outsize = 0;
796 ErrorCode::from(err)
797 },
798 }
799}