Skip to content

Commit

Permalink
JPEG-XL: Better 'effort' and adding noise synth (GoogleChromeLabs#1039)
Browse files Browse the repository at this point in the history
  • Loading branch information
jakearchibald authored Aug 27, 2021
1 parent 6b08cd2 commit 0233048
Show file tree
Hide file tree
Showing 16 changed files with 49 additions and 31 deletions.
Binary file modified codecs/jxl/dec/jxl_dec.wasm
Binary file not shown.
Binary file modified codecs/jxl/dec/jxl_node_dec.wasm
Binary file not shown.
17 changes: 9 additions & 8 deletions codecs/jxl/enc/jxl_enc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,13 @@ using namespace emscripten;
thread_local const val Uint8Array = val::global("Uint8Array");

struct JXLOptions {
// 1 = slowest
// 7 = fastest
int speed;
int effort;
float quality;
bool progressive;
int epf;
int nearLossless;
bool lossyPalette;
size_t decodingSpeedTier;
float photonNoiseIso;
};

val encode(std::string image, int width, int height, JXLOptions options) {
Expand All @@ -33,11 +31,14 @@ val encode(std::string image, int width, int height, JXLOptions options) {
pool_ptr = &pool;
#endif

size_t st = 10 - options.effort;
cparams.speed_tier = jxl::SpeedTier(st);

cparams.epf = options.epf;
cparams.speed_tier = static_cast<jxl::SpeedTier>(options.speed);
cparams.decoding_speed_tier = options.decodingSpeedTier;
cparams.photon_noise_iso = options.photonNoiseIso;

if (options.lossyPalette || options.nearLossless) {
if (options.lossyPalette) {
cparams.lossy_palette = true;
cparams.palette_colors = 0;
cparams.options.predictor = jxl::Predictor::Zero;
Expand Down Expand Up @@ -106,12 +107,12 @@ val encode(std::string image, int width, int height, JXLOptions options) {

EMSCRIPTEN_BINDINGS(my_module) {
value_object<JXLOptions>("JXLOptions")
.field("speed", &JXLOptions::speed)
.field("effort", &JXLOptions::effort)
.field("quality", &JXLOptions::quality)
.field("progressive", &JXLOptions::progressive)
.field("nearLossless", &JXLOptions::nearLossless)
.field("lossyPalette", &JXLOptions::lossyPalette)
.field("decodingSpeedTier", &JXLOptions::decodingSpeedTier)
.field("photonNoiseIso", &JXLOptions::photonNoiseIso)
.field("epf", &JXLOptions::epf);

function("encode", &encode);
Expand Down
4 changes: 2 additions & 2 deletions codecs/jxl/enc/jxl_enc.d.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
export interface EncodeOptions {
speed: number;
effort: number;
quality: number;
progressive: boolean;
epf: number;
nearLossless: number;
lossyPalette: boolean;
decodingSpeedTier: number;
photonNoiseIso: number;
}

export interface JXLModule extends EmscriptenWasm.Module {
Expand Down
2 changes: 1 addition & 1 deletion codecs/jxl/enc/jxl_enc.js

Large diffs are not rendered by default.

Binary file modified codecs/jxl/enc/jxl_enc.wasm
Binary file not shown.
2 changes: 1 addition & 1 deletion codecs/jxl/enc/jxl_enc_mt.js

Large diffs are not rendered by default.

Binary file modified codecs/jxl/enc/jxl_enc_mt.wasm
Binary file not shown.
2 changes: 1 addition & 1 deletion codecs/jxl/enc/jxl_enc_mt_simd.js

Large diffs are not rendered by default.

Binary file modified codecs/jxl/enc/jxl_enc_mt_simd.wasm
Binary file not shown.
2 changes: 1 addition & 1 deletion codecs/jxl/enc/jxl_node_enc.js

Large diffs are not rendered by default.

Binary file modified codecs/jxl/enc/jxl_node_enc.wasm
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const REFLECTED_ATTRIBUTES = [
'disabled',
];

function getPrescision(value: string): number {
function getPrecision(value: string): number {
const afterDecimal = value.split('.')[1];
return afterDecimal ? afterDecimal.length : 0;
}
Expand Down Expand Up @@ -112,18 +112,24 @@ class RangeInputElement extends HTMLElement {
this.dispatchEvent(retargetted);
};

private _getDisplayValue(value: number): string {
if (value >= 10000) return (value / 1000).toFixed(1) + 'k';

const labelPrecision =
Number(this.labelPrecision) || getPrecision(this.step) || 0;
return labelPrecision
? value.toFixed(labelPrecision)
: Math.round(value).toString();
}

private _update = () => {
// Not connected?
if (!this._valueDisplay) return;
const value = Number(this.value) || 0;
const min = Number(this.min) || 0;
const max = Number(this.max) || 100;
const labelPrecision =
Number(this.labelPrecision) || getPrescision(this.step) || 0;
const percent = (100 * (value - min)) / (max - min);
const displayValue = labelPrecision
? value.toFixed(labelPrecision)
: Math.round(value).toString();
const displayValue = this._getDisplayValue(value);

this._valueDisplay!.textContent = displayValue;
this.style.setProperty('--value-percent', percent + '%');
Expand Down
2 changes: 1 addition & 1 deletion src/client/lazy-app/Compress/Options/Range/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
text-decoration-style: dotted;
text-decoration-color: var(--main-theme-color);
text-underline-position: under;
width: 48px;
width: 54px;
position: relative;
left: 5px;

Expand Down
27 changes: 19 additions & 8 deletions src/features/encoders/jxl/client/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,9 @@ interface State {
slightLoss: boolean;
autoEdgePreservingFilter: boolean;
decodingSpeedTier: number;
photonNoiseIso: number;
}

const maxSpeed = 7;

export class Options extends Component<Props, State> {
static getDerivedStateFromProps(
props: Props,
Expand All @@ -47,14 +46,15 @@ export class Options extends Component<Props, State> {
// Create default form state from options
return {
options,
effort: maxSpeed - options.speed,
effort: options.effort,
quality: options.quality,
progressive: options.progressive,
edgePreservingFilter: options.epf === -1 ? 2 : options.epf,
lossless: options.quality === 100,
slightLoss: options.lossyPalette,
autoEdgePreservingFilter: options.epf === -1,
decodingSpeedTier: options.decodingSpeedTier,
photonNoiseIso: options.photonNoiseIso,
};
}

Expand Down Expand Up @@ -87,15 +87,15 @@ export class Options extends Component<Props, State> {
};

const newOptions: EncodeOptions = {
speed: maxSpeed - optionState.effort,
effort: optionState.effort,
quality: optionState.lossless ? 100 : optionState.quality,
progressive: optionState.progressive,
epf: optionState.autoEdgePreservingFilter
? -1
: optionState.edgePreservingFilter,
nearLossless: 0,
lossyPalette: optionState.lossless ? optionState.slightLoss : false,
decodingSpeedTier: optionState.decodingSpeedTier,
photonNoiseIso: optionState.photonNoiseIso,
};

// Updating options, so we don't recalculate in getDerivedStateFromProps.
Expand All @@ -121,6 +121,7 @@ export class Options extends Component<Props, State> {
slightLoss,
autoEdgePreservingFilter,
decodingSpeedTier,
photonNoiseIso,
}: State,
) {
// I'm rendering both lossy and lossless forms, as it becomes much easier when
Expand Down Expand Up @@ -164,7 +165,6 @@ export class Options extends Component<Props, State> {
<label class={style.optionToggle}>
Auto edge filter
<Checkbox
name="autoEdgeFilter"
checked={autoEdgePreservingFilter}
onChange={this._inputChange(
'autoEdgePreservingFilter',
Expand Down Expand Up @@ -199,6 +199,17 @@ export class Options extends Component<Props, State> {
Optimise for decoding speed (worse compression):
</Range>
</div>
<div class={style.optionOneCell}>
<Range
min="0"
max="50000"
step="100"
value={photonNoiseIso}
onInput={this._inputChange('photonNoiseIso', 'number')}
>
Noise equivalent to ISO:
</Range>
</div>
</div>
)}
</Expander>
Expand All @@ -212,8 +223,8 @@ export class Options extends Component<Props, State> {
</label>
<div class={style.optionOneCell}>
<Range
min="0"
max={maxSpeed - 1}
min="3"
max="9"
value={effort}
onInput={this._inputChange('effort', 'number')}
>
Expand Down
4 changes: 2 additions & 2 deletions src/features/encoders/jxl/shared/meta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ export const label = 'JPEG XL (beta)';
export const mimeType = 'image/jxl';
export const extension = 'jxl';
export const defaultOptions: EncodeOptions = {
speed: 4,
effort: 7,
quality: 75,
progressive: false,
epf: -1,
nearLossless: 0,
lossyPalette: false,
decodingSpeedTier: 0,
photonNoiseIso: 0,
};

0 comments on commit 0233048

Please sign in to comment.