check / check (push) Waiting to run
A JPEG XL source is accepted, and orig of one is JPEG XL. The format jxl works in plain and encrypted URLs and on the generator page, served as image/jxl; auto chooses it first when Accept names image/jxl. govips sends libvips a JPEG XL distance, which overrides the quality, so q becomes a distance, keeping 100 lossy. Metadata is removed from the image before the JPEG XL save, as govips cannot have libvips strip it, and the image is given 72 dpi so that the EXIF block libvips 8.16 adds holds nothing from the source. The sRGB conversion moved ahead of the format switch, and a CMYK image with no ICC profile is converted to sRGB, as libvips cannot save CMYK as JPEG XL. Model: opus-5-5
162 lines
6.4 KiB
HTML
162 lines
6.4 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Pixa - URL Generator</title>
|
|
<link rel="stylesheet" href="/static/style.css">
|
|
</head>
|
|
<body>
|
|
<div class="page">
|
|
<header>
|
|
<h1>Pixa URL Generator</h1>
|
|
<a href="/logout">
|
|
Logout
|
|
</a>
|
|
</header>
|
|
|
|
{{if .GeneratedURL}}
|
|
<div class="result">
|
|
<h2>Generated URL</h2>
|
|
<div>
|
|
<input
|
|
type="text"
|
|
readonly
|
|
value="{{.GeneratedURL}}"
|
|
id="generated-url"
|
|
>
|
|
<button id="copy-url">
|
|
Copy
|
|
</button>
|
|
</div>
|
|
<p>
|
|
Expires: {{.ExpiresAt}}
|
|
</p>
|
|
</div>
|
|
{{end}}
|
|
|
|
{{if .Error}}
|
|
<div class="error">
|
|
{{.Error}}
|
|
</div>
|
|
{{end}}
|
|
|
|
<form method="POST" action="/generate" class="card">
|
|
{{ .CSRFField }}
|
|
<div>
|
|
<label for="url">
|
|
Source URL
|
|
</label>
|
|
<input
|
|
type="url"
|
|
id="url"
|
|
name="url"
|
|
required
|
|
placeholder="https://example.com/image.jpg"
|
|
value="{{.FormURL}}"
|
|
>
|
|
</div>
|
|
|
|
<div class="columns">
|
|
<div>
|
|
<label for="width">
|
|
Width
|
|
</label>
|
|
<input
|
|
type="number"
|
|
id="width"
|
|
name="width"
|
|
min="0"
|
|
max="8192"
|
|
value="{{if .FormWidth}}{{.FormWidth}}{{else}}0{{end}}"
|
|
placeholder="0 = original"
|
|
>
|
|
</div>
|
|
<div>
|
|
<label for="height">
|
|
Height
|
|
</label>
|
|
<input
|
|
type="number"
|
|
id="height"
|
|
name="height"
|
|
min="0"
|
|
max="8192"
|
|
value="{{if .FormHeight}}{{.FormHeight}}{{else}}0{{end}}"
|
|
placeholder="0 = original"
|
|
>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="columns">
|
|
<div>
|
|
<label for="format">
|
|
Format
|
|
</label>
|
|
<select id="format" name="format">
|
|
<option value="orig" {{if eq .FormFormat "orig"}}selected{{end}}>Original</option>
|
|
<option value="auto" {{if eq .FormFormat "auto"}}selected{{end}}>Auto (JPEG XL, AVIF, WebP or JPEG)</option>
|
|
<option value="jpeg" {{if eq .FormFormat "jpeg"}}selected{{end}}>JPEG</option>
|
|
<option value="png" {{if eq .FormFormat "png"}}selected{{end}}>PNG</option>
|
|
<option value="webp" {{if eq .FormFormat "webp"}}selected{{end}}>WebP</option>
|
|
<option value="avif" {{if eq .FormFormat "avif"}}selected{{end}}>AVIF</option>
|
|
<option value="jxl" {{if eq .FormFormat "jxl"}}selected{{end}}>JPEG XL</option>
|
|
<option value="gif" {{if eq .FormFormat "gif"}}selected{{end}}>GIF</option>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label for="quality">
|
|
Quality
|
|
</label>
|
|
<select id="quality" name="quality">
|
|
<option value="25" {{if eq .FormQuality "25"}}selected{{end}}>Potato</option>
|
|
<option value="50" {{if eq .FormQuality "50"}}selected{{end}}>Low</option>
|
|
<option value="70" {{if eq .FormQuality "70"}}selected{{end}}>Medium</option>
|
|
<option value="85" {{if or (eq .FormQuality "85") (eq .FormQuality "")}}selected{{end}}>High</option>
|
|
<option value="100" {{if eq .FormQuality "100"}}selected{{end}}>Ultra</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="columns">
|
|
<div>
|
|
<label for="fit">
|
|
Fit Mode
|
|
</label>
|
|
<select id="fit" name="fit">
|
|
<option value="cover" {{if eq .FormFit "cover"}}selected{{end}}>Cover</option>
|
|
<option value="contain" {{if eq .FormFit "contain"}}selected{{end}}>Contain</option>
|
|
<option value="fill" {{if eq .FormFit "fill"}}selected{{end}}>Fill</option>
|
|
<option value="inside" {{if eq .FormFit "inside"}}selected{{end}}>Inside</option>
|
|
<option value="outside" {{if eq .FormFit "outside"}}selected{{end}}>Outside</option>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label for="ttl">
|
|
Expires In
|
|
</label>
|
|
<select id="ttl" name="ttl">
|
|
<option value="0" {{if or (eq .FormTTL "0") (eq .FormTTL "")}}selected{{end}}>Never</option>
|
|
<option value="60" {{if eq .FormTTL "60"}}selected{{end}}>1 minute</option>
|
|
<option value="3600" {{if eq .FormTTL "3600"}}selected{{end}}>1 hour</option>
|
|
<option value="86400" {{if eq .FormTTL "86400"}}selected{{end}}>1 day</option>
|
|
<option value="604800" {{if eq .FormTTL "604800"}}selected{{end}}>1 week</option>
|
|
<option value="2592000" {{if eq .FormTTL "2592000"}}selected{{end}}>30 days</option>
|
|
<option value="31536000" {{if eq .FormTTL "31536000"}}selected{{end}}>1 year</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
<button type="submit">
|
|
Generate Encrypted URL
|
|
</button>
|
|
</form>
|
|
|
|
<p class="note">
|
|
Generated URLs are encrypted and cannot be modified. They will expire at the specified time.
|
|
</p>
|
|
</div>
|
|
<script src="/static/generator.js"></script>
|
|
</body>
|
|
</html>
|