Skip to content

Commit d1ee8c9

Browse files
committed
release: 1.0.0
2 parents 1182a57 + 8e8ea7f commit d1ee8c9

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

89 files changed

+3950
-4318
lines changed

.github/workflows/ci.yaml

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,18 +48,36 @@ jobs:
4848
- name: Apt Dependencies
4949
run: |
5050
sudo apt-get update
51-
sudo apt-get install -y cmake g++ gcc git librust-gdk4-dev librust-gtk4-dev libgtk-3-dev libatk1.0-dev make nasm ninja-build
51+
sudo apt-get install -y cmake g++ gcc git make nasm ninja-build
5252
5353
- name: Build
5454
run: |
5555
cargo build --target ${{ matrix.target }}
5656
cargo build --release --target ${{ matrix.target }}
5757
58-
- name: Clippy
58+
- name: Clippy (Workspace)
5959
run: |
6060
cargo clippy --release --target ${{ matrix.target }}
6161
cargo clippy --release --all-features --target ${{ matrix.target }}
6262
63+
- name: Clippy (Feature Combinations)
64+
run: |
65+
cargo clippy --release -p refract_core --no-default-features --features=avif --target ${{ matrix.target }}
66+
cargo clippy --release -p refract_core --no-default-features --features=avif,jpeg --target ${{ matrix.target }}
67+
cargo clippy --release -p refract_core --no-default-features --features=avif,jpeg,jxl --target ${{ matrix.target }}
68+
cargo clippy --release -p refract_core --no-default-features --features=avif,jpeg,jxl,png --target ${{ matrix.target }}
69+
cargo clippy --release -p refract_core --no-default-features --features=avif,jpeg,jxl,png,webp --target ${{ matrix.target }}
70+
cargo clippy --release -p refract_core --no-default-features --features=jpeg --target ${{ matrix.target }}
71+
cargo clippy --release -p refract_core --no-default-features --features=jpeg,jxl --target ${{ matrix.target }}
72+
cargo clippy --release -p refract_core --no-default-features --features=jpeg,jxl,png --target ${{ matrix.target }}
73+
cargo clippy --release -p refract_core --no-default-features --features=jpeg,jxl,png,webp --target ${{ matrix.target }}
74+
cargo clippy --release -p refract_core --no-default-features --features=jxl --target ${{ matrix.target }}
75+
cargo clippy --release -p refract_core --no-default-features --features=jxl,png --target ${{ matrix.target }}
76+
cargo clippy --release -p refract_core --no-default-features --features=jxl,png,webp --target ${{ matrix.target }}
77+
cargo clippy --release -p refract_core --no-default-features --features=png --target ${{ matrix.target }}
78+
cargo clippy --release -p refract_core --no-default-features --features=png,webp --target ${{ matrix.target }}
79+
cargo clippy --release -p refract_core --no-default-features --features=webp --target ${{ matrix.target }}
80+
6381
- name: Tests (Debug)
6482
run: |
6583
cargo test --target ${{ matrix.target }}

.gitignore

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
1-
**.avif
21
**.br
32
**.deb
43
**.gz
5-
**.jxl
6-
**.webp
7-
**/*.glade\#
8-
**/*.glade~
94
**/target/
105
/Cargo.lock
116
/doc/
7+
/ref-bin*
8+
/skel/assets/**.avif
9+
/skel/assets/**.jxl
10+
/skel/assets/**.webp
11+
/skel/png-test-suite/**.avif
12+
/skel/png-test-suite/**.jxl
13+
/skel/png-test-suite/**.webp

CREDITS.md

Lines changed: 293 additions & 58 deletions
Large diffs are not rendered by default.

README.md

Lines changed: 71 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,39 @@
1-
# Refract GTK
1+
# Refract
22

33
[![ci](https://img.shields.io/github/actions/workflow/status/Blobfolio/refract/ci.yaml?style=flat-square&label=ci)](https://github.com/Blobfolio/refract/actions)
44
[![deps.rs](https://deps.rs/repo/github/blobfolio/refract/status.svg?style=flat-square&label=deps.rs)](https://deps.rs/repo/github/blobfolio/refract)<br>
55
[![license](https://img.shields.io/badge/license-wtfpl-ff1493?style=flat-square)](https://en.wikipedia.org/wiki/WTFPL)
66
[![contributions welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square&label=contributions)](https://github.com/Blobfolio/refract/issues)
77

8-
Refract is a guided image conversion tool written in [Rust](https://www.rust-lang.org/) for x86-64 Linux systems with [GTK](https://www.gtk.org/) `v3.22.30` or later.
8+
Refract is a cross-platform[\*](#installation) guided image conversion tool.
99

10-
It takes [JPEG](https://en.wikipedia.org/wiki/JPEG) and [PNG](https://en.wikipedia.org/wiki/Portable_Network_Graphics) image sources and produces [AVIF](https://en.wikipedia.org/wiki/AV1#AV1_Image_File_Format_(AVIF)), [JPEG XL](https://en.wikipedia.org/wiki/JPEG_XL), and [WebP](https://en.wikipedia.org/wiki/WebP) clones.
10+
It takes [JPEG](https://en.wikipedia.org/wiki/JPEG) and [PNG](https://en.wikipedia.org/wiki/Portable_Network_Graphics) image sources and produces [AVIF](https://en.wikipedia.org/wiki/AV1#AV1_Image_File_Format_(AVIF)), [JPEG XL](https://en.wikipedia.org/wiki/JPEG_XL), and [WebP](https://en.wikipedia.org/wiki/WebP) copies.
1111

12-
<img src="https://github.com/Blobfolio/refract/raw/master/skel/gallery/screen0.png" width="30%" alt="The start screen. Nice and clean."></img> <img src="https://github.com/Blobfolio/refract/raw/master/skel/gallery/screen1.png" width="30%" alt="Viewing a PNG source image."></img> <img src="https://github.com/Blobfolio/refract/raw/master/skel/gallery/screen2.png" width="30%" alt="Previewing a WebP candidate to Discard or Keep."></img>
12+
![A tour of the program in action.](skel/gallery/refract.webp)
1313

14-
The program works like an eye doctor Refraction Test. It generates candidate images at various qualities, asking at each step how it looks, and uses the feedback (you provide) to arrive at the smallest possible "acceptable" output.
14+
The program is named for and works something like an optometrist's refraction test, presenting a series of feedback-driven candidate images — what looks better, this… or this? This… or this? — until the subjective "best" option is found (or found to be impossible).
1515

1616
Hence "guided".
1717

18-
The beauty of this approach is that it moots the need for exhaustive testing. Refract's quality stepping works by selecting the mid-point between moving min/max boundaries. Similar to a binary search, each answer you provide halves the range of remaining possibilities, allowing the final, perfect result to be discovered in just 5-10 steps instead of 100+.
18+
The beauty of this sort of approach is it moots the need for exhaustive testing.
1919

20+
Every Yay and Nay you provide halve the number of possibilities remaining to be tested. The ideal copy, whatever and wherever it might be, can be found in a handful of steps instead of a hundred.
2021

2122

22-
## Why?
23-
24-
Every image is different. The idea of a "Magic Bullet" format is a myth.
25-
26-
If you want to truly maximize the quality and size of next-gen copies, you cannot rely on hardcoded constants or automated [SSIM](https://en.wikipedia.org/wiki/Structural_similarity) analysis; your images would come out over- or under-compressed.
2723

28-
You have to actually _use your eyes_. And you have to pay attention to the resulting file sizes. Sometimes newer formats will result in _larger_ output than the original source, defeating the purpose. Haha.
29-
30-
While you can do all of this manually — running multiple programs hundreds of times for each and every source you want to convert — that would be incredibly tedious and easy to screw up.
24+
## Why?
3125

32-
Refract helps make that manual process _less_ tedious and _more_ foolproof.
26+
Every image is different.
3327

34-
It automatically uses the strongest (slowest) possible compression settings for each format, keeps track of file sizes and qualities along the way, supports batch processing, and reduces the number of conversion tests by around 90%.
28+
There is no such thing as a one-size-fits-all quality setting, or even a one-size-fits-all image format.
3529

36-
Should you use it for every image ever?
30+
Whether you're looking for perfect copies or merely passable ones, the only way to be sure you're not producing over- or under-compressed images is to _use your eyes_.
3731

38-
No, probably not.
32+
Done manually, you'd need to use a lot more — your brain, for starters — but thankfully most of the rest of the process _can_ be automated.
3933

40-
The next generation formats, particularly AVIF and JPEG XL, require a lot of computation to eek out their extra byte savings. All those minutes will add up quickly.
34+
That's where refract comes in.
4135

42-
But if you're looking to obsessively optimize a small project or single web page, Refract is definitely the way to go!
36+
It keeps track of the details so you don't have to.
4337

4438

4539

@@ -48,47 +42,63 @@ But if you're looking to obsessively optimize a small project or single web page
4842
| Format | Decoding (Input/Display) | Encoding (Output) |
4943
| ------ | -------- | -------- |
5044
| JPEG | Yes, except CMYK and 16-bit lossless. ||
51-
| PNG | Yes* ||
45+
| PNG | Yes ||
5246
| AVIF | Yes | Lossless, lossy, `RGB`, and `YCbCr` |
5347
| JPEG XL | Yes* | Lossless, lossy. |
5448
| WebP | Yes* | Lossless, lossy. |
5549

56-
*Refract does not support animated images. Without going too far down _that_ rabbit hole, let's just say that if GIF can't handle the job, it should be a video, not an image.
57-
58-
In other words, Refract takes JPEG and PNG sources — either individual files or entire directory trees — and turns them into AVIF, JPEG XL, and/or WebP outputs.
50+
In short, Refract takes JPEG and PNG sources — either individual files or entire directory trees — and turns them into AVIF, JPEG XL, and/or WebP outputs.
5951

6052
Refract implements [`libavif`](https://github.com/AOMediaCodec/libavif), [`libjxl`](https://github.com/libjxl/libjxl), and [`libwebp`](https://chromium.googlesource.com/webm/libwebp/) directly. This not only ensures full standards compliance and feature/performance parity with each format's official conversion tools — `avifenc`, `cjxl`, and `cwebp` respectively — it also means you don't need any of that crap separately installed to use it.
6153

6254
All conversion takes place at Pixel Level and is intended for displays with an sRGB color space (e.g. web browsers). Gamma correction, color profiles, and other metadata are ignored and stripped out when saving next-gen copies.
6355

56+
All conversions are performed using the maximum/slowest (general) encoder settings, ensuring the smallest possible output. Refract also explicitly tracks the input and output file sizes to save you having to review counter-productive combinations.
57+
6458

6559

6660
## Usage
6761

6862
Refract is pretty straightforward:
6963

70-
1. Tweak the settings — via the `Settings` menu — as desired.
71-
2. Load a single image or an entire directory. You can either use the links in the `File` menu, or drag-and-drop images straight onto the window from your file browser.
72-
3. Sit back and wait for any feedback or save prompts.
64+
0. Open the program;
65+
1. Choose the output format(s) and tweak any other settings you want;
66+
2. Choose one or more JPEG/PNG source files to crunch;
67+
3. Sit back and wait for the feedback prompts;
68+
69+
### Feedback
70+
71+
Lossless conversions require no human supervision. Being lossless, all that really matters is that shit gets smaller, and refract can figure _that_ out on its own. ;)
72+
73+
Lossy conversions are another matter since, by their very nature, information is lost in translation.
74+
75+
For those, refract will present a series of "candidate" images to you, one at a time, in a simple A/B fashion for easy comparison with the original sources.
76+
77+
The "feedback" comes in the form of two buttons — "reject" and "accept" — which can be thought of as answers to the question: Are you happy with this copy?
7378

74-
For best results, be sure to optimize your input sources before re-encoding them with Refract. (The CLI tool [flaca](https://github.com/Blobfolio/flaca) is great for this, and fully automatic.)
79+
If it looks like what you want it to, great!, accept it. If not, reject it. Refract will raise or lower the quality of the next candidate accordingly.
7580

76-
For keyboard aficionados, the following hot-keys may be used:
81+
Rinse and repeat.
7782

78-
| Action | Key(s) |
79-
| ------ | ------ |
80-
| Open File | `CTRL + o` |
81-
| Open Directory | `SHIFT + CTRL + o` |
82-
| Toggle Dark Mode | `CTRL + n` |
83-
| Toggle A/B View | `SPACE` |
84-
| Discard Candidate | `d` |
85-
| Keep Candidate | `k` |
83+
The smallest of the accepted candidates, if any, will be saved to disk at the end of the process, the rest forgotten like a passing dream.
84+
85+
Then it's back around again for the next input/output pair!
86+
87+
### Pro Tip
88+
89+
JPEG and PNG are actually quite _good_ and, properly encoded, can provide _better_ compression than some — or all — of the possible next-gen alternatives.
90+
91+
(This is especially true for lossless conversions; a well-optimized PNG is _not_ something you'd want to meet in a dark alley!)
92+
93+
For best — or at least more honest — results, take some time to optimize your sources with a tool like [flaca](https://github.com/Blobfolio/flaca/) _before_ feeding them to refract.
94+
95+
Two things are twice as many things as one thing,<sup>\[citation needed\]</sup> but being the obsessive person you are — normal people wouldn't be doing _either_ — you'll sleep better knowing no bytes have gone unsaved.
8696

8797

8898

8999
## CLI Usage
90100

91-
Refract is a _graphical_ program, but when launching from the command line, you can override the default settings and/or queue up images to re-encode.
101+
Refract is a graphical program, but the startup settings and/or queue can be configured via command line if desired.
92102

93103
```bash
94104
refract [FLAGS] [OPTIONS] <PATH(S)>...
@@ -104,50 +114,47 @@ refract [FLAGS] [OPTIONS] <PATH(S)>...
104114
| `--no-lossless` | Skip lossless encoding passes. |
105115
| `--no-lossy` | Skip lossy encoding passes. |
106116
| `--no-ycbcr` | Skip AVIF YCbCr encoding passes. |
107-
108-
Note: The flags only affect the initial program state. All settings can still be managed through the program's dropdown menus after launch.
117+
| `--save-auto` | Automatically save successful conversions to their source paths — with new extensions appended — instead of popping a file dialogue for confirmation. |
109118

110119
| Option | Description |
111120
| ------ | ----------- |
112121
| `-l` / `--list` | Read (absolute) image and/or directory paths from this text file, one path per line. Set to "-" to read from STDIN. This is equivalent to specifying the same paths as trailing arguments, but can be cleaner if there are lots of them. |
113122

114-
When image and/or directory paths are passed as trailing arguments (`<PATH(S)>...`), and/or the `-l`/`--list` option is used, Refract will start crunching all valid sources as soon as the program launches.
115-
116123

117124

118125
## Installation
119126

120-
Debian and Ubuntu users can just grab the pre-built `.deb` package from the [release page](https://github.com/Blobfolio/refract/releases/latest).
127+
Pre-built packages for x86-64 CPU architectures are available for Debian and Ubuntu users on the [release page](https://github.com/Blobfolio/refract/releases/latest), and to Arch Linux users via [AUR](https://aur.archlinux.org/packages/refract-bin).
121128

122-
Arch Linux users can install Refract via [AUR](https://aur.archlinux.org/packages/refract-bin) (community-maintained).
129+
To use refract in other environments, it'll needs to be built from source.
123130

124-
While specifically written for use on x86-64 Linux systems, both Rust and GTK3 are cross-platform, so you may well be able to build it from source on other 64-bit Unix systems using `Cargo`:
131+
Thankfully, [Rust](https://www.rust-lang.org/)/[Cargo](https://github.com/rust-lang/cargo) make this pretty easy:
125132

126133
```bash
127-
# Clone the repository.
128-
git clone https://github.com/Blobfolio/refract.git
134+
# Install the build dependencies. Ubuntu and Debian users, for example,
135+
# can run:
136+
sudo apt-get install -y cmake g++ gcc git make nasm ninja-build
137+
138+
# Build and install refract:
139+
cargo install \
140+
--git https://github.com/Blobfolio/refract.git \
141+
--bin refract
142+
```
129143

130-
# Move into the directory.
131-
cd refract
144+
### Build Dependencies
132145

133-
# Build with Cargo. Feel free to add other build flags as desired.
134-
cargo build --release
135-
```
146+
The extra build dependencies (required by all the damn image codecs) will vary by environment, but at a minimum you'll need up-to-date C and C++ compilers, `cmake`, `git` (obviously), `make`, `nasm`, and `ninja-build`.
136147

137-
Cargo _will_ handle the entire build process for you, however many of Refract's dependencies have heavy `build.rs` scripts requiring additional system libraries. (Who'd have thought image decoders and encoders were complicated?!)
148+
Cargo should pop an error if anything's missing. If that happens, just find/install the missing dep and give `cargo install` another shot.
138149

139-
At a minimum, you'll need up-to-date versions of:
150+
If you wind up needing something not on this list, please [open an issue](https://github.com/Blobfolio/refract/issues) so it can be given a mention. ;)
140151

141-
* Cmake
142-
* `gcc`/`g++`
143-
* Git
144-
* Make
145-
* NASM
146-
* Ninja
147-
* Rust/Cargo
152+
### Runtime Dependencies
148153

149-
GTK3 is a whole other monster, requiring the `-dev` packages for (at least) ATK, Cairo, GDK, GLIB, GTK, Pango, and Pixbuf. Thankfully, many distributions offer meta packages to make GTK dependency resolution easier. On Debian Bullseye, for example, installing `librust-gtk-dev` and `librust-gdk-dev` should just about cover everything.
154+
On Linux, the file dialogues require one of `xdg-desktop-portal-[gnome, gtk, kde]` or `zenity`, user's choice.
150155

151-
[This post](https://github.com/Blobfolio/refract/issues/3#issuecomment-1086924244) provides a good breakdown of how to set up a minimal Docker build environment for Refract.
156+
In theory, _None of the Above_ should work too, provided you use the CLI to enqueue image paths and enable automatic saving with the `--save-auto` flag (along with any other settings tweaks you might want):
152157

153-
If you end up building Refract on a non-Debian system — Red Hat, MacOS, etc. — please let us know what that setup looked like so we can update the docs. Users of those systems will no doubt appreciate it. :)
158+
```bash
159+
refract --save-auto /path/to/image.jpg
160+
```

justfile

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,14 @@ release_dir := justfile_directory() + "/release"
2828

2929

3030

31+
#export RUSTFLAGS := "-Ctarget-cpu=x86-64-v3 -Cllvm-args=--cost-kind=throughput -Clinker-plugin-lto -Clink-arg=-fuse-ld=lld"
32+
#export CC := "clang"
33+
#export CXX := "clang++"
34+
#export CFLAGS := "-Wall -Wextra -flto -march=x86-64-v3"
35+
#export CXXFLAGS := "-Wall -Wextra -flto -march=x86-64-v3"
36+
37+
38+
3139
# Build Release!
3240
@build:
3341
cargo build \
@@ -68,12 +76,43 @@ release_dir := justfile_directory() + "/release"
6876
# Clippy.
6977
@clippy:
7078
clear
79+
80+
fyi task "All Features"
7181
cargo clippy \
7282
--release \
7383
--workspace \
7484
--all-features \
7585
--target-dir "{{ cargo_dir }}"
7686

87+
just _clippy avif
88+
just _clippy avif,jpeg
89+
just _clippy avif,jpeg,jxl
90+
just _clippy avif,jpeg,jxl,png
91+
just _clippy avif,jpeg,jxl,png,webp
92+
93+
just _clippy jpeg
94+
just _clippy jpeg,jxl
95+
just _clippy jpeg,jxl,png
96+
just _clippy jpeg,jxl,png,webp
97+
98+
just _clippy jxl
99+
just _clippy jxl,png
100+
just _clippy jxl,png,webp
101+
102+
just _clippy png
103+
just _clippy png,webp
104+
105+
just _clippy webp
106+
107+
@_clippy FEATURES:
108+
fyi task "Features: {{ FEATURES }}"
109+
cargo clippy \
110+
--release \
111+
-p refract_core \
112+
--no-default-features \
113+
--features "{{ FEATURES }}" \
114+
--target-dir "{{ cargo_dir }}"
115+
77116

78117
# Generate CREDITS.
79118
@credits:

0 commit comments

Comments
 (0)