Skip to content

Commit

Permalink
release: 3.1.6
Browse files Browse the repository at this point in the history
  • Loading branch information
joshstoik1 committed Aug 13, 2024
2 parents 5dcad27 + 29504c9 commit 16e8305
Show file tree
Hide file tree
Showing 13 changed files with 185 additions and 254 deletions.
25 changes: 13 additions & 12 deletions CREDITS.md
Original file line number Diff line number Diff line change
@@ -1,40 +1,41 @@
# Project Dependencies
Package: flaca
Version: 3.1.5
Generated: 2024-07-26 04:46:44 UTC
Version: 3.1.6
Generated: 2024-08-13 18:34:14 UTC

| Package | Version | Author(s) | License |
| ---- | ---- | ---- | ---- |
| [ahash](https://github.com/tkaitchuck/ahash) | 0.8.11 | [Tom Kaitchuck](mailto:tom.kaitchuck@gmail.com) | Apache-2.0 or MIT |
| [argyle](https://github.com/Blobfolio/argyle) | 0.7.2 | [Blobfolio, LLC.](mailto:hello@blobfolio.com) | WTFPL |
| [argyle](https://github.com/Blobfolio/argyle) | 0.8.0 | [Blobfolio, LLC.](mailto:hello@blobfolio.com) | WTFPL |
| [bitvec](https://github.com/bitvecto-rs/bitvec) | 1.0.1 | | MIT |
| [bytecount](https://github.com/llogiq/bytecount) | 0.6.8 | [Andre Bogus](mailto:bogusandre@gmail.de) and [Joshua Landau](mailto:joshua@landau.ws) | Apache-2.0 or MIT |
| [bytemuck](https://github.com/Lokathor/bytemuck) | 1.16.1 | [Lokathor](mailto:zefria@gmail.com) | Apache-2.0, MIT, or Zlib |
| [bytemuck](https://github.com/Lokathor/bytemuck) | 1.16.3 | [Lokathor](mailto:zefria@gmail.com) | Apache-2.0, MIT, or Zlib |
| [cfg-if](https://github.com/alexcrichton/cfg-if) | 1.0.0 | [Alex Crichton](mailto:alex@alexcrichton.com) | Apache-2.0 or MIT |
| [crc32fast](https://github.com/srijs/rust-crc32fast) | 1.4.2 | [Sam Rijs](mailto:srijs@airpost.net) and [Alex Crichton](mailto:alex@alexcrichton.com) | Apache-2.0 or MIT |
| [crossbeam-channel](https://github.com/crossbeam-rs/crossbeam) | 0.5.13 | | Apache-2.0 or MIT |
| [crossbeam-utils](https://github.com/crossbeam-rs/crossbeam) | 0.8.20 | | Apache-2.0 or MIT |
| [ctrlc](https://github.com/Detegr/rust-ctrlc.git) | 3.4.4 | [Antti Keränen](mailto:detegr@gmail.com) | Apache-2.0 or MIT |
| [ctrlc](https://github.com/Detegr/rust-ctrlc.git) | 3.4.5 | [Antti Keränen](mailto:detegr@gmail.com) | Apache-2.0 or MIT |
| [dactyl](https://github.com/Blobfolio/dactyl) | 0.7.2 | [Blobfolio, LLC.](mailto:hello@blobfolio.com) | WTFPL |
| [dowser](https://github.com/Blobfolio/dowser) | 0.9.2 | [Blobfolio, LLC.](mailto:hello@blobfolio.com) | WTFPL |
| [equivalent](https://github.com/cuviper/equivalent) | 1.0.1 | | Apache-2.0 or MIT |
| [fastrand](https://github.com/smol-rs/fastrand) | 2.1.0 | [Stjepan Glavina](mailto:stjepang@gmail.com) | Apache-2.0 or MIT |
| flapfli | 3.1.5 | [Josh Stoik](mailto:josh@blobfolio.com) | WTFPL |
| flapfli | 3.1.6 | [Josh Stoik](mailto:josh@blobfolio.com) | WTFPL |
| [funty](https://github.com/myrrlyn/funty) | 2.0.0 | [myrrlyn](mailto:self@myrrlyn.dev) | MIT |
| [fyi_msg](https://github.com/Blobfolio/fyi) | 0.13.6 | [Blobfolio, LLC.](mailto:hello@blobfolio.com) | WTFPL |
| [hashbrown](https://github.com/rust-lang/hashbrown) | 0.14.5 | [Amanieu d'Antras](mailto:amanieu@gmail.com) | Apache-2.0 or MIT |
| [indexmap](https://github.com/indexmap-rs/indexmap) | 2.2.6 | | Apache-2.0 or MIT |
| [indexmap](https://github.com/indexmap-rs/indexmap) | 2.3.0 | | Apache-2.0 or MIT |
| [libc](https://github.com/rust-lang/libc) | 0.2.155 | The Rust Project Developers | Apache-2.0 or MIT |
| [libdeflate-sys](https://github.com/adamkewley/libdeflater) | 1.20.0 | [Adam Kewley](mailto:contact@adamkewley.com) | Apache-2.0 |
| [libdeflater](https://github.com/adamkewley/libdeflater) | 1.20.0 | [Adam Kewley](mailto:contact@adamkewley.com) | Apache-2.0 |
| [libdeflate-sys](https://github.com/adamkewley/libdeflater) | 1.21.0 | [Adam Kewley](mailto:contact@adamkewley.com) | Apache-2.0 |
| [libdeflater](https://github.com/adamkewley/libdeflater) | 1.21.0 | [Adam Kewley](mailto:contact@adamkewley.com) | Apache-2.0 |
| [log](https://github.com/rust-lang/log) | 0.4.22 | The Rust Project Developers | Apache-2.0 or MIT |
| [mozjpeg-sys](https://github.com/kornelski/mozjpeg-sys.git) | 2.2.0 | [Kornel](mailto:kornel@geekhood.net) | IJG AND Zlib AND BSD-3-Clause |
| [mozjpeg-sys](https://github.com/kornelski/mozjpeg-sys.git) | 2.2.1 | [Kornel](mailto:kornel@geekhood.net) | IJG AND Zlib AND BSD-3-Clause |
| [once_cell](https://github.com/matklad/once_cell) | 1.19.0 | [Aleksey Kladov](mailto:aleksey.kladov@gmail.com) | Apache-2.0 or MIT |
| [oxipng](https://github.com/shssoichiro/oxipng) | 9.1.2 | [Joshua Holmer](mailto:jholmer.in@gmail.com) | MIT |
| [radium](https://github.com/bitvecto-rs/radium) | 0.7.0 | [Nika Layzell](mailto:nika@thelayzells.com) and [myrrlyn](mailto:self@myrrlyn.dev) | MIT |
| [rgb](https://github.com/kornelski/rust-rgb) | 0.8.45 | [Kornel Lesiński](mailto:kornel@geekhood.net) | MIT |
| [rgb](https://github.com/kornelski/rust-rgb) | 0.8.48 | [Kornel Lesiński](mailto:kornel@geekhood.net) and [James Forster](mailto:james.forsterer@gmail.com) | MIT |
| [rustc-hash](https://github.com/rust-lang-nursery/rustc-hash) | 1.1.0 | The Rust Project Developers | Apache-2.0 or MIT |
| [tap](https://github.com/myrrlyn/tap) | 1.0.1 | [Elliott Linder](mailto:elliott.darfink@gmail.com) and [myrrlyn](mailto:self@myrrlyn.dev) | MIT |
| [tempfile](https://github.com/Stebalien/tempfile) | 3.10.1 | [Steven Allen](mailto:steven@stebalien.com), The Rust Project Developers, [Ashley Mannix](mailto:ashleymannix@live.com.au), and [Jason White](mailto:me@jasonwhite.io) | Apache-2.0 or MIT |
| [tempfile](https://github.com/Stebalien/tempfile) | 3.12.0 | [Steven Allen](mailto:steven@stebalien.com), The Rust Project Developers, [Ashley Mannix](mailto:ashleymannix@live.com.au), and [Jason White](mailto:me@jasonwhite.io) | Apache-2.0 or MIT |
| [terminal_size](https://github.com/eminence/terminal-size) | 0.3.0 | [Andrew Chin](mailto:achin@eminence32.net) | Apache-2.0 or MIT |
| [unicode-width](https://github.com/unicode-rs/unicode-width) | 0.1.13 | [kwantam](mailto:kwantam@gmail.com) and [Manish Goregaokar](mailto:manishsmail@gmail.com) | Apache-2.0 or MIT |
| [write_atomic](https://github.com/Blobfolio/write_atomic) | 0.5.0 | [Blobfolio, LLC.](mailto:hello@blobfolio.com) | WTFPL |
Expand Down
11 changes: 6 additions & 5 deletions flaca/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "flaca"
version = "3.1.5"
version = "3.1.6"
license = "WTFPL"
authors = ["Josh Stoik <josh@blobfolio.com>"]
edition = "2021"
Expand Down Expand Up @@ -112,9 +112,9 @@ items = [
]

[dependencies]
argyle = "0.7.*"
argyle = "0.8.*"
crossbeam-channel = "=0.5.*"
ctrlc = "=3.4.4"
ctrlc = "=3.4.5"
dactyl = "0.7.*"
dowser = "0.9.*"
libc = "0.2.*"
Expand All @@ -129,8 +129,9 @@ version = "0.13.*"
features = [ "progress" ]

[dependencies.mozjpeg-sys]
version = "=2.2.0"
features = [ "jpegtran" ]
version = "=2.2.1"
default-features = false
features = [ "jpegtran", "nasm_simd", "unwinding" ]

[dependencies.oxipng]
version = "=9.1.2"
Expand Down
42 changes: 26 additions & 16 deletions flaca/src/image/jpegtran.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,15 @@ use mozjpeg_sys::{
jpeg_common_struct,
jpeg_compress_struct,
jpeg_copy_critical_parameters,
jpeg_create_compress,
jpeg_create_decompress,
jpeg_CreateCompress,
jpeg_decompress_struct,
jpeg_destroy_compress,
jpeg_destroy_decompress,
jpeg_error_mgr,
jpeg_finish_compress,
jpeg_finish_decompress,
JPEG_LIB_VERSION,
jpeg_mem_dest,
jpeg_mem_src,
jpeg_read_coefficients,
Expand All @@ -54,6 +55,7 @@ use std::{
},
marker::PhantomPinned,
ops::Deref,
ptr::NonNull,
};


Expand All @@ -77,7 +79,7 @@ impl Deref for EncodedJPEG {

#[allow(clippy::cast_possible_truncation, unsafe_code)]
fn deref(&self) -> &Self::Target {
if self.is_empty() { &[] }
if self.is_null() { &[] }
else {
unsafe { std::slice::from_raw_parts(self.buf, self.size as usize) }
}
Expand All @@ -87,9 +89,9 @@ impl Deref for EncodedJPEG {
impl Drop for EncodedJPEG {
#[allow(unsafe_code)]
fn drop(&mut self) {
if ! self.is_empty() {
if ! self.buf.is_null() {
unsafe { libc::free(self.buf.cast::<c_void>()); }
self.buf = std::ptr::null_mut();
self.buf = std::ptr::null_mut(); // Probably unnecessary?
}
}
}
Expand All @@ -103,8 +105,14 @@ impl EncodedJPEG {
}
}

/// # Is Empty?
fn is_empty(&self) -> bool { self.size == 0 || self.buf.is_null() }
/// # Is Null?
///
/// This is essentially an `is_empty`, returning `true` if the length value
/// is zero or the buffer pointer is literally null.
///
/// (The name was chosen to help avoid conflicts with dereferenced slice
/// methods.)
fn is_null(&self) -> bool { self.size == 0 || self.buf.is_null() }
}


Expand Down Expand Up @@ -225,7 +233,7 @@ pub(super) fn optimize(src: &[u8]) -> Option<EncodedJPEG> {
unsafe { jpeg_finish_decompress(&mut srcinfo.cinfo); }

// Return it if we got it!
if happy && ! out.is_empty() && out.size < src_size { Some(out) }
if happy && ! out.is_null() && out.size < src_size { Some(out) }
else { None }
}

Expand Down Expand Up @@ -255,7 +263,6 @@ impl<'a> From<&'a [u8]> for JpegSrcInfo<'a> {
// Set up the error, then the struct.
out.cinfo.common.err = std::ptr::addr_of_mut!(*out.err);
jpeg_create_decompress(&mut out.cinfo);
out.cinfo.common.progress = std::ptr::null_mut();
}

out
Expand All @@ -280,7 +287,7 @@ impl<'a> Drop for JpegSrcInfo<'a> {
/// but its error is a raw pointer because `mozjpeg` is really weird. Haha.
struct JpegDstInfo {
cinfo: jpeg_compress_struct,
err: *mut jpeg_error_mgr,
err: NonNull<jpeg_error_mgr>,
_pin: PhantomPinned,
}

Expand All @@ -289,18 +296,23 @@ impl From<&mut JpegSrcInfo<'_>> for JpegDstInfo {
fn from(src: &mut JpegSrcInfo<'_>) -> Self {
let mut out = Self {
cinfo: unsafe { std::mem::zeroed() },
err: Box::into_raw(new_err()),
// Safety: boxes point somewhere!
err: unsafe { NonNull::new_unchecked(Box::into_raw(new_err())) },
_pin: PhantomPinned,
};

unsafe {
// Set up the error, then the struct.
out.cinfo.common.err = std::ptr::addr_of_mut!(*out.err);
jpeg_create_compress(&mut out.cinfo);
out.cinfo.common.err = out.err.as_ptr();
jpeg_CreateCompress(&mut out.cinfo, JPEG_LIB_VERSION, size_of_val(&out.cinfo));

// Note: depending on the compiler/flags, JPEG compression can
// segfault if this isn't explicitly made null. Not sure why it
// isn't an always/never behavior…
out.cinfo.common.progress = std::ptr::null_mut();

// Sync the source trace level with the destination.
src.err.trace_level = (*out.err).trace_level;
src.err.trace_level = out.err.as_ref().trace_level;
}

out
Expand All @@ -312,9 +324,7 @@ impl Drop for JpegDstInfo {
fn drop(&mut self) {
unsafe {
jpeg_destroy_compress(&mut self.cinfo);

// The error pointer is no longer accessible.
let _ = Box::from_raw(self.err);
let _ = Box::from_raw(self.err.as_ptr());
}
}
}
Expand Down
103 changes: 42 additions & 61 deletions flaca/src/image/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,14 @@ pub(super) mod kind;

use crate::MAX_RESOLUTION;
use kind::ImageKind;
use oxipng::Options as OxipngOptions;
use std::{
path::Path,
sync::{
atomic::Ordering::Relaxed,
OnceLock,
},
sync::atomic::Ordering::Relaxed,
};
use super::EncodingError;



static OXIPNG_OPTIONS: OnceLock<OxipngOptions> = OnceLock::new();



#[allow(clippy::inline_always)] // This is the hottest path we've got!
#[inline(always)]
/// # Encode Image.
Expand Down Expand Up @@ -131,7 +123,47 @@ fn encode_mozjpeg(raw: &mut Vec<u8>) {
/// oxipng -o 3 -s -a -i 0 --fix
/// ```
fn encode_oxipng(raw: &mut Vec<u8>) {
if let Ok(mut new) = oxipng::optimize_from_memory(raw, OXIPNG_OPTIONS.get_or_init(oxipng_options)) {
use oxipng::{
Deflaters,
IndexSet,
Interlacing,
Options,
RowFilter,
StripChunks,
};

thread_local!(
static OXI: Options = Options {
fix_errors: true,
force: false,
filter: IndexSet::from([
RowFilter::None,
RowFilter::Average,
RowFilter::BigEnt,
RowFilter::Bigrams,
RowFilter::Brute,
RowFilter::Entropy,
RowFilter::MinSum,
RowFilter::Paeth,
RowFilter::Sub,
RowFilter::Up,
]),
interlace: Some(Interlacing::None),
optimize_alpha: true,
bit_depth_reduction: true,
color_type_reduction: true,
palette_reduction: true,
grayscale_reduction: true,
idat_recoding: true,
scale_16: false,
strip: StripChunks::All,
deflate: Deflaters::Libdeflater { compression: 12 },
fast_evaluation: false,
timeout: None,
}
);

if let Ok(mut new) = OXI.with(|opts| oxipng::optimize_from_memory(raw, opts)) {
if new.len() < raw.len() && ImageKind::is_png(&new) {
std::mem::swap(raw, &mut new);
}
Expand All @@ -155,54 +187,3 @@ fn encode_zopflipng(raw: &mut Vec<u8>) {
}
}
}

#[inline(never)]
/// # Generate Oxipng Options.
///
/// This returns the strongest possible Oxipng compression profile (minus
/// the zopfli bits, which we try in a separate pass).
///
/// This is basically just "preset 6", with:
/// * Error fixing enabled;
/// * Libdeflater;
/// * All the alpha optimizations;
/// * Interlacing disabled;
/// * All headers stripped;
fn oxipng_options() -> OxipngOptions {
use oxipng::{
Deflaters,
IndexSet,
Interlacing,
RowFilter,
StripChunks,
};

OxipngOptions {
fix_errors: true,
force: false,
filter: IndexSet::from([
RowFilter::None,
RowFilter::Average,
RowFilter::BigEnt,
RowFilter::Bigrams,
RowFilter::Brute,
RowFilter::Entropy,
RowFilter::MinSum,
RowFilter::Paeth,
RowFilter::Sub,
RowFilter::Up,
]),
interlace: Some(Interlacing::None),
optimize_alpha: true,
bit_depth_reduction: true,
color_type_reduction: true,
palette_reduction: true,
grayscale_reduction: true,
idat_recoding: true,
scale_16: false,
strip: StripChunks::All,
deflate: Deflaters::Libdeflater { compression: 12 },
fast_evaluation: false,
timeout: None,
}
}
2 changes: 1 addition & 1 deletion flapfli/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "flapfli"
version = "3.1.5"
version = "3.1.6"
license = "WTFPL"
authors = ["Josh Stoik <josh@blobfolio.com>"]
edition = "2021"
Expand Down
19 changes: 18 additions & 1 deletion flapfli/src/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ impl Drop for EncodedPNG {
// method, but only if it actually got allocated.
if let Some(nn) = NonNull::new(self.buf) {
unsafe { flapfli_free(nn); }
self.buf = std::ptr::null_mut(); // Is this necessary?
self.buf = std::ptr::null_mut(); // Probably unnecessary?
}
}
}
Expand Down Expand Up @@ -210,3 +210,20 @@ const unsafe fn size_and_ptr(ptr: NonNull<u8>) -> (NonNull<u8>, NonZeroUsize) {

(size_and_data_ptr, size)
}



#[cfg(test)]
mod tests {
#[test]
/// # No Drop Checks.
///
/// Prove we aren't missing out by not running drop-in-place or whatever on
/// usize/byte slices.
fn t_nodrop() {
use std::mem::needs_drop;

assert!(! needs_drop::<[usize]>());
assert!(! needs_drop::<[u8]>());
}
}
Loading

0 comments on commit 16e8305

Please sign in to comment.