Skip to content

Commit 19a86e4

Browse files
committed
release: 1.7.0
2 parents a350461 + 35c375f commit 19a86e4

9 files changed

Lines changed: 122 additions & 101 deletions

File tree

CREDITS.md

Lines changed: 66 additions & 64 deletions
Large diffs are not rendered by default.

refract/Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "refract"
3-
version = "1.6.0"
3+
version = "1.7.0"
44
license = "WTFPL"
55
authors = ["Josh Stoik <josh@blobfolio.com>"]
66
edition = "2024"
@@ -106,9 +106,9 @@ features = [ "png" ]
106106
argyle = "0.15.*"
107107
dactyl = "0.13.*"
108108
dowser = "0.18.*"
109-
fyi_ansi = "2.6.*"
109+
fyi_ansi = "2.7.*"
110110
iced_runtime = "0.14.0" # Iced doesn't re-export Allocation, etc.
111-
open = "=5.3.6"
111+
open = "5.4.*"
112112
rfd = "=0.17.2"
113113
unicode-width = "0.2.*"
114114
write_atomic = "0.7.*"

refract/src/img.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ fn tile_checkers(tile: &[u8; 14_400]) -> image::Handle {
109109
// First things first, let's repeat the entire tile once, width-wise,
110110
// since the broken-up writes aren't terribly performant.
111111
let mut pixels = Vec::<u8>::with_capacity(WIDTH * HEIGHT * 4);
112-
for line in tile.chunks_exact(TILE * 4) {
112+
for line in tile.as_chunks::<{TILE * 4}>().0 {
113113
for _ in 0..WIDTH / TILE { pixels.extend_from_slice(line); }
114114
}
115115

refract_core/Cargo.toml

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "refract_core"
3-
version = "1.6.0"
3+
version = "1.7.0"
44
license = "WTFPL"
55
authors = ["Josh Stoik <josh@blobfolio.com>"]
66
edition = "2024"
@@ -10,7 +10,7 @@ readme = "README.md"
1010
publish = false
1111

1212
[dependencies]
13-
fyi_ansi = "2.6.*"
13+
fyi_ansi = "2.7.*"
1414

1515
[dependencies.dactyl]
1616
version = "0.13.*"
@@ -42,9 +42,10 @@ default-features = false
4242
features = [ "codec-aom" ]
4343
optional = true
4444

45-
[dependencies.libwebp-sys2]
46-
version = "=0.2.0"
47-
features = [ "static" ]
45+
[dependencies.libwebp-sys]
46+
version = "=0.14.4"
47+
default-features = false
48+
features = [ "std" ]
4849
optional = true
4950

5051
[dependencies.rgb] # Match lodepng's dependency listing.
@@ -72,4 +73,4 @@ jxl = [ "dactyl", "jpegxl-sys", "link-cplusplus" ]
7273
png = [ "lodepng" ]
7374

7475
# Support WebP.
75-
webp = [ "dactyl", "libwebp-sys2" ]
76+
webp = [ "dactyl", "libwebp-sys" ]

refract_core/src/input.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -342,15 +342,17 @@ impl Input {
342342
match self.depth {
343343
ColorKind::Rgba => Cow::Borrowed(&self.pixels),
344344
ColorKind::Rgb => Cow::Owned(
345-
self.pixels.chunks_exact(3)
345+
self.pixels.as_chunks::<3>().0
346+
.iter()
346347
.fold(Vec::with_capacity(size), |mut acc, px| {
347348
acc.extend_from_slice(px); // Push RGB.
348349
acc.push(255); // Push Alpha.
349350
acc
350351
})
351352
),
352353
ColorKind::GreyAlpha => Cow::Owned(
353-
self.pixels.chunks_exact(2)
354+
self.pixels.as_chunks::<2>().0
355+
.iter()
354356
.fold(Vec::with_capacity(size), |mut acc, px| {
355357
acc.extend_from_slice(&[px[0], px[0], px[0], px[1]]);
356358
acc
@@ -390,11 +392,12 @@ impl Input {
390392

391393
let (buf, depth): (Vec<u8>, ColorKind) = match self.color {
392394
ColorKind::Grey => (
393-
self.pixels.chunks_exact(4).map(|px| px[0]).collect(),
395+
self.pixels.as_chunks::<4>().0.iter().map(|px| px[0]).collect(),
394396
ColorKind::Grey,
395397
),
396398
ColorKind::GreyAlpha => (
397-
self.pixels.chunks_exact(4)
399+
self.pixels.as_chunks::<4>().0
400+
.iter()
398401
.fold(Vec::with_capacity(self.width() * self.height() * 2), |mut acc, px| {
399402
acc.push(px[0]); // Keep one color.
400403
acc.push(px[3]); // Keep alpha.
@@ -403,7 +406,8 @@ impl Input {
403406
ColorKind::GreyAlpha,
404407
),
405408
ColorKind::Rgb => (
406-
self.pixels.chunks_exact(4)
409+
self.pixels.as_chunks::<4>().0
410+
.iter()
407411
.fold(Vec::with_capacity(self.width() * self.height() * 3), |mut acc, px| {
408412
acc.extend_from_slice(&px[..3]); // Keep RGB.
409413
acc

refract_core/src/kind/color.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ impl ColorKind {
106106
pub fn from_rgba(src: &[u8]) -> Self {
107107
let mut color: bool = false;
108108
let mut alpha: bool = false;
109-
for px in src.chunks_exact(4) {
109+
for px in src.as_chunks::<4>().0 {
110110
if ! color && (px[0] != px[1] || px[0] != px[2]) {
111111
color = true;
112112
if alpha { return Self::Rgba; }

refract_core/src/kind/png/alpha.rs

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,11 @@ impl Nine {
5050
///
5151
/// This returns true if any of the pixels in the set have an alpha value
5252
/// of zero.
53-
fn has_invisible(&self) -> bool { self.0.chunks_exact(4).any(|px| px[3] == 0) }
53+
fn has_invisible(&self) -> bool {
54+
self.0.as_chunks::<4>().0
55+
.iter()
56+
.any(|px| px[3] == 0)
57+
}
5458

5559
#[inline]
5660
/// # Is Semi-Transparent?
@@ -77,7 +81,8 @@ impl Nine {
7781
/// If the result turns out to be identical to the original value, `None`
7882
/// is returned.
7983
fn averaged(&self) -> Option<[u8; 4]> {
80-
let (r, g, b) = self.0.chunks_exact(4)
84+
let (r, g, b) = self.0.as_chunks::<4>().0
85+
.iter()
8186
.fold((0_u16, 0_u16, 0_u16), |mut acc, px| {
8287
acc.0 += u16::from(px[0]);
8388
acc.1 += u16::from(px[1]);
@@ -126,7 +131,8 @@ impl Nine {
126131
/// If no weighting is possible, or if the result winds up identical to the
127132
/// original, `None` is returned.
128133
fn weighted(&self) -> Option<[u8; 4]> {
129-
let (r, g, b, weight) = self.0.chunks_exact(4)
134+
let (r, g, b, weight) = self.0.as_chunks::<4>().0
135+
.iter()
130136
.fold((0_u32, 0_u32, 0_u32, 0_u32), |mut acc, px| {
131137
if px[3] > 0 {
132138
let weight = 256 - u32::from(px[3]);
@@ -166,7 +172,8 @@ impl Nine {
166172
pub(super) fn clean_alpha(img: &mut [u8], width: usize, height: usize) {
167173
if let Some(avg) = neutral_pixel(img, width, height) {
168174
// Set all invisible pixels to said neutral color.
169-
img.chunks_exact_mut(4)
175+
img.as_chunks_mut::<4>().0
176+
.iter_mut()
170177
.filter(|px| px[3] == 0)
171178
.for_each(|px| { px.copy_from_slice(&avg); });
172179

@@ -284,7 +291,7 @@ where Cb: FnMut(Nine) {
284291

285292
// Start each row with 0, 0, 1 columns. We know there's always going to
286293
// be a +1 because we refuse images with widths < 3.
287-
for (chunk, k) in nine.0.chunks_exact_mut(12).zip([top, middle, bottom]) {
294+
for (chunk, k) in nine.0.as_chunks_mut::<12>().0.iter_mut().zip([top, middle, bottom]) {
288295
chunk[..4].copy_from_slice(&img[k..k + 4]);
289296
chunk[4..].copy_from_slice(&img[k..k + 8]);
290297
}
@@ -295,14 +302,14 @@ where Cb: FnMut(Nine) {
295302
// Loop the columns.
296303
for x in 1..width {
297304
// Shift the old middle and right positions down for each row.
298-
for chunk in nine.0.chunks_exact_mut(12) {
305+
for chunk in nine.0.as_chunks_mut::<12>().0 {
299306
chunk.copy_within(4.., 0);
300307
}
301308

302309
// Copy in the new right positions, if any.
303310
if x + 1 < width {
304311
let right = (x + 1) * 4;
305-
for (chunk, k) in nine.0.chunks_exact_mut(12).zip([top, middle, bottom]) {
312+
for (chunk, k) in nine.0.as_chunks_mut::<12>().0.iter_mut().zip([top, middle, bottom]) {
306313
chunk[8..].copy_from_slice(&img[k + right..k + right + 4]);
307314
}
308315
}

refract_core/src/kind/webp.rs

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*!
22
# `Refract`: `WebP` Handling
33
4-
This uses [`libwebp-sys2`](https://crates.io/crates/libwebp-sys2) bindings to Google's
4+
This uses [`libwebp-sys`](https://crates.io/crates/libwebp-sys) bindings to Google's
55
`libwebp`. Operations should be equivalent to the corresponding `cwebp` output.
66
*/
77

@@ -17,9 +17,7 @@ use crate::{
1717
},
1818
};
1919
use libwebp_sys::{
20-
WEBP_MAX_DIMENSION,
2120
WebPConfig,
22-
WebPConfigInit,
2321
WebPConfigLosslessPreset,
2422
WebPEncode,
2523
WebPMemoryWrite,
@@ -29,7 +27,6 @@ use libwebp_sys::{
2927
WebPPicture,
3028
WebPPictureFree,
3129
WebPPictureImportRGBA,
32-
WebPPictureInit,
3330
WebPValidateConfig,
3431
};
3532
use std::{
@@ -38,6 +35,20 @@ use std::{
3835
};
3936

4037

38+
/// # Max Dimensions.
39+
///
40+
/// Dimensions are expressed as `i32` everywhere but this constant. Haha.
41+
const WEBP_MAX_DIMENSION: i32 = libwebp_sys::WEBP_MAX_DIMENSION.cast_signed();
42+
43+
/// # Sanity Checks.
44+
const _: () = {
45+
assert!(
46+
libwebp_sys::WEBP_MAX_DIMENSION <= (i32::MAX as u32),
47+
"Bug: WEBP_MAX_DIMENSION doesn't fit in i32.",
48+
);
49+
};
50+
51+
4152

4253
/// # `WebP` Image.
4354
pub(crate) struct ImageWebp;
@@ -155,10 +166,9 @@ impl TryFrom<&Input> for LibWebpPicture {
155166
}
156167

157168
// Set up the picture struct.
158-
// Safety: libwebp expects zeroed memory.
159-
let mut out = Self(unsafe { std::mem::zeroed() });
160-
// Safety: this is an FFI call…
161-
maybe_die(unsafe { WebPPictureInit(&raw mut out.0) })?;
169+
let mut out = WebPPicture::new()
170+
.map_err(|()| RefractError::Encode)
171+
.map(Self)?;
162172

163173
out.0.use_argb = 1;
164174
out.0.width = width;
@@ -306,10 +316,7 @@ fn encode(
306316
/// cwebp -lossless -z 9 -q 100
307317
/// ```
308318
fn make_config(quality: Option<NonZeroU8>) -> Result<WebPConfig, RefractError> {
309-
// Safety: the subsequent call expects zeroed memory.
310-
let mut config: WebPConfig = unsafe { std::mem::zeroed() };
311-
// Safety: this is an FFI call…
312-
maybe_die(unsafe { WebPConfigInit(&raw mut config) })?;
319+
let mut config = WebPConfig::new().map_err(|()| RefractError::Encode)?;
313320
// Safety: this is an FFI call…
314321
maybe_die(unsafe { WebPValidateConfig(&raw const config) })?;
315322

release/man/refract.1

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
.TH "REFRACT" "1" "July 2026" "refract v1.6.0" "User Commands"
1+
.TH "REFRACT" "1" "August 2026" "refract v1.7.0" "User Commands"
22
.SH NAME
3-
REFRACT \- Manual page for refract v1.6.0.
3+
REFRACT \- Manual page for refract v1.7.0.
44
.SH DESCRIPTION
55
Guided AVIF/JPEG XL/WebP conversion for JPEG and PNG sources.
66
.SS USAGE:

0 commit comments

Comments
 (0)