Skip to content

Commit 440870f

Browse files
authored
Update gif.ski 1.10.1 (#293)
1 parent 4f66318 commit 440870f

File tree

5 files changed

+94
-48
lines changed

5 files changed

+94
-48
lines changed

gifski-api/Cargo.lock

Lines changed: 38 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

gifski-api/Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ license = "AGPL-3.0-or-later"
1010
name = "gifski"
1111
readme = "README.md"
1212
repository = "https://github.com/ImageOptim/gifski"
13-
version = "1.10.0"
13+
version = "1.10.1"
1414
autobins = false
1515
edition = "2021"
1616
rust-version = "1.63"
@@ -87,5 +87,5 @@ strip = true
8787
[package.metadata.docs.rs]
8888
targets = ["x86_64-unknown-linux-gnu"]
8989

90-
# [patch.crates-io]
91-
# ffmpeg-sys-next = { rev = "78458039d5fac99354f9cb078869f3be3f3af5fb", git = "https://github.com/kornelski/rust-ffmpeg-sys-1"}
90+
[patch.crates-io]
91+
ffmpeg-sys-next = { rev = "78458039d5fac99354f9cb078869f3be3f3af5fb", git = "https://github.com/kornelski/rust-ffmpeg-sys-1"}

gifski-api/src/c_api.rs

Lines changed: 38 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -340,13 +340,17 @@ pub unsafe extern "C" fn gifski_set_progress_callback(handle: *const GifskiHandl
340340
Some(g) => g,
341341
None => return GifskiError::NULL_ARG,
342342
};
343-
let t = g.write_thread.lock().unwrap();
344-
if t.0 {
343+
if g.write_thread.lock().map_or(true, |t| t.0) {
345344
eprintln!("tried to set progress callback after writing has already started");
346345
return GifskiError::INVALID_STATE;
347346
}
348-
*g.progress.lock().unwrap() = Some(ProgressCallback::new(cb, user_data));
349-
GifskiError::OK
347+
match g.progress.lock() {
348+
Ok(mut progress) => {
349+
*progress = Some(ProgressCallback::new(cb, user_data));
350+
GifskiError::OK
351+
},
352+
Err(_) => GifskiError::THREAD_LOST,
353+
}
350354
}
351355

352356
/// Start writing to the `destination`. This has to be called before any frames are added.
@@ -364,7 +368,7 @@ pub unsafe extern "C" fn gifski_set_file_output(handle: *const GifskiHandle, des
364368
Ok(res) => res,
365369
Err(err) => return err,
366370
};
367-
gifski_write_thread_start(g, file, Some(path))
371+
gifski_write_thread_start(g, file, Some(path)).err().unwrap_or(GifskiError::OK)
368372
}
369373

370374

@@ -377,7 +381,7 @@ fn prepare_for_file_writing(g: &GifskiHandleInternal, destination: *const c_char
377381
} else {
378382
return Err(GifskiError::INVALID_INPUT);
379383
};
380-
let t = g.write_thread.lock().unwrap();
384+
let t = g.write_thread.lock().map_err(|_| GifskiError::THREAD_LOST)?;
381385
if t.0 {
382386
eprintln!("tried to start writing for the second time, after it has already started");
383387
return Err(GifskiError::INVALID_STATE);
@@ -435,24 +439,21 @@ pub unsafe extern "C" fn gifski_set_write_callback(handle: *const GifskiHandle,
435439
None => return GifskiError::NULL_ARG,
436440
};
437441
let writer = CallbackWriter { cb, user_data };
438-
gifski_write_thread_start(g, writer, None)
442+
gifski_write_thread_start(g, writer, None).err().unwrap_or(GifskiError::OK)
439443
}
440444

441-
fn gifski_write_thread_start<W: 'static + Write + Send>(g: &GifskiHandleInternal, file: W, path: Option<PathBuf>) -> GifskiError {
442-
let mut t = g.write_thread.lock().unwrap();
445+
fn gifski_write_thread_start<W: 'static + Write + Send>(g: &GifskiHandleInternal, file: W, path: Option<PathBuf>) -> Result<(), GifskiError> {
446+
let mut t = g.write_thread.lock().map_err(|_| GifskiError::THREAD_LOST)?;
443447
if t.0 {
444448
eprintln!("gifski_set_file_output/gifski_set_write_callback has been called already");
445-
return GifskiError::INVALID_STATE;
449+
return Err(GifskiError::INVALID_STATE);
446450
}
447-
let writer = g.writer.lock().unwrap().take();
448-
let mut user_progress = g.progress.lock().unwrap().take();
451+
let writer = g.writer.lock().map_err(|_| GifskiError::THREAD_LOST)?.take();
452+
let mut user_progress = g.progress.lock().map_err(|_| GifskiError::THREAD_LOST)?.take();
449453
let handle = thread::Builder::new().name("c-write".into()).spawn(move || {
450454
if let Some(writer) = writer {
451-
let mut progress: &mut dyn ProgressReporter = &mut NoProgress {};
452-
if let Some(cb) = &mut user_progress {
453-
progress = &mut *cb;
454-
}
455-
match writer.write(file, progress).into() {
455+
let progress = user_progress.as_mut().map(|m| m as &mut dyn ProgressReporter);
456+
match writer.write(file, progress.unwrap_or(&mut NoProgress {})).into() {
456457
res @ (GifskiError::OK | GifskiError::ALREADY_EXISTS) => res,
457458
err => {
458459
if let Some(path) = path {
@@ -469,9 +470,9 @@ fn gifski_write_thread_start<W: 'static + Write + Send>(g: &GifskiHandleInterna
469470
match handle {
470471
Ok(handle) => {
471472
*t = (true, Some(handle));
472-
GifskiError::OK
473+
Ok(())
473474
},
474-
Err(_) => GifskiError::THREAD_LOST,
475+
Err(_) => Err(GifskiError::THREAD_LOST),
475476
}
476477
}
477478

@@ -497,14 +498,27 @@ pub unsafe extern "C" fn gifski_finish(g: *const GifskiHandle) -> GifskiError {
497498
}
498499
let g = Arc::from_raw(g.cast::<GifskiHandleInternal>());
499500

500-
// dropping of the collector (if any) completes writing
501-
*g.collector.lock().unwrap() = None;
501+
match g.collector.lock() {
502+
// dropping of the collector (if any) completes writing
503+
Ok(mut lock) => *lock = None,
504+
Err(_) => {
505+
eprintln!("warning: collector thread crashed");
506+
},
507+
};
508+
509+
let thread = match g.write_thread.lock() {
510+
Ok(mut writer) => writer.1.take(),
511+
Err(_) => return GifskiError::THREAD_LOST,
512+
};
502513

503-
let thread = g.write_thread.lock().unwrap().1.take();
504514
if let Some(thread) = thread {
505-
thread.join().unwrap_or(GifskiError::THREAD_LOST)
515+
thread.join().map_err(|e| {
516+
let msg = e.downcast_ref::<String>().map(|s| s.as_str())
517+
.or_else(|| e.downcast_ref::<&str>().copied()).unwrap_or("unknown panic");
518+
eprintln!("writer crashed (this is a bug): {msg}");
519+
}).unwrap_or(GifskiError::THREAD_LOST)
506520
} else {
507-
eprintln!("gifski_finish called before any output has been set");
521+
eprintln!("warning: gifski_finish called before any output has been set");
508522
GifskiError::OK // this will become INVALID_STATE once sync write support is dropped
509523
}
510524
}

gifski-api/src/error.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use quick_error::quick_error;
55
quick_error! {
66
#[derive(Debug)]
77
pub enum Error {
8+
/// Internal error
89
ThreadSend {
910
display("Internal error; unexpectedly aborted")
1011
}

gifski-api/src/lib.rs

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,7 @@ impl Writer {
429429
}
430430

431431
let mut res = liq.quantize(&mut img)?;
432-
res.set_dithering_level((f32::from(settings.s.quality) / 50.0 - 1.).max(0.))?;
432+
res.set_dithering_level((f32::from(settings.s.quality) / 50.0 - 1.).max(0.2))?;
433433

434434
let mut out = Vec::new();
435435
out.try_reserve_exact(width*height).map_err(imagequant::liq_error::from)?;
@@ -528,10 +528,10 @@ impl Writer {
528528
Self::remap_frames(remap_queue_recv, write_queue)
529529
})?;
530530
let res0 = Self::write_frames(write_queue_recv, writer, &settings_ext, reporter);
531-
let res1 = resize_thread.join().map_err(|_| Error::ThreadSend)?;
532-
let res2 = diff_thread.join().map_err(|_| Error::ThreadSend)?;
533-
let res3 = quant_thread.join().map_err(|_| Error::ThreadSend)?;
534-
let res4 = remap_thread.join().map_err(|_| Error::ThreadSend)?;
531+
let res1 = resize_thread.join().map_err(handle_join_error)?;
532+
let res2 = diff_thread.join().map_err(handle_join_error)?;
533+
let res3 = quant_thread.join().map_err(handle_join_error)?;
534+
let res4 = remap_thread.join().map_err(handle_join_error)?;
535535
combine_res(combine_res(combine_res(res0, res1), combine_res(res2, res3)), res4)
536536
}
537537

@@ -673,7 +673,7 @@ impl Writer {
673673
gif::DisposalMethod::Keep
674674
};
675675

676-
let importance_map = importance_map.take().unwrap(); // always set at the beginning
676+
let importance_map = importance_map.take().ok_or(Error::ThreadSend)?; // always set at the beginning
677677

678678
if !prev_frame_keeps || importance_map.iter().any(|&px| px > 0) {
679679
if prev_frame_keeps {
@@ -701,7 +701,7 @@ impl Writer {
701701
Ok(())
702702
}, move |(end_pts, image, mut importance_map, ordinal_frame_number, frame_index, dispose, first_frame_has_transparency, prev_frame_keeps)| {
703703
let needs_transparency = frame_index > 0 || (frame_index == 0 && first_frame_has_transparency);
704-
let (liq, remap, liq_image, out_buf) = Self::quantize(image, &importance_map, frame_index == 0, needs_transparency, prev_frame_keeps, settings).unwrap();
704+
let (liq, remap, liq_image, out_buf) = Self::quantize(image, &importance_map, frame_index == 0, needs_transparency, prev_frame_keeps, settings)?;
705705
let max_loss = settings.gifsicle_loss();
706706
for imp in &mut importance_map {
707707
// encoding assumes rgba background looks like encoded background, which is not true for lossy
@@ -874,3 +874,10 @@ impl<T> PushInCapacity<T> for Vec<T> {
874874
}
875875
}
876876
}
877+
878+
fn handle_join_error(err: Box<dyn std::any::Any + Send>) -> Error {
879+
let msg = err.downcast_ref::<String>().map(|s| s.as_str())
880+
.or_else(|| err.downcast_ref::<&str>().copied()).unwrap_or("unknown panic");
881+
eprintln!("thread crashed (this is a bug): {msg}");
882+
Error::ThreadSend
883+
}

0 commit comments

Comments
 (0)