054dd25079
Renames the app throughout: page titles, eyebrow/version labels, Docker startup banner, main.py's header docstring, and the repo links in the footer (now pointing at git.djeex.fr/Djeex/instameex and github.com/Djeex/instameex, matching the renamed Gitea/GitHub repos). Docker image and container are now named "instameex" too (docker/compose.yaml), replacing the old instagram-hdr naming. Adds the new logo: logo.svg is wired up as the favicon on both pages, and logo-long.svg replaces the plain-text "Instameex" eyebrow on the upload page as a properly sized wordmark. The startup banner box width was recalculated by hand for the new content (name plus Source:/Mirror: links instead of the old license/upstream-credit lines), verified against a real container rebuild so the border characters stay aligned. kostis-kounadis/instagram-hdr-assembler references are left alone throughout (README and banner): that's the separate upstream project this app's gain-map logic is adapted from, not this app's own name.
127 lines
5.2 KiB
HTML
127 lines
5.2 KiB
HTML
<!doctype html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title>Instameex</title>
|
|
<link rel="icon" type="image/svg+xml" href="{{ url_for('static', filename='img/logo.svg') }}">
|
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
|
|
</head>
|
|
<body>
|
|
<div class="wrap">
|
|
<img class="logo" src="{{ url_for('static', filename='img/logo-long.svg') }}" alt="Instameex">
|
|
<h1>Build your HDR JPEG for Instagram</h1>
|
|
<p class="subtitle">Drop your SDR export and your HDR export from Lightroom / Camera Raw. The script does the rest — gain map, 4:2:0 subsampling, Instagram metadata injection. Add more pairs to process several photos in one go.</p>
|
|
|
|
<div class="card">
|
|
{% if error %}
|
|
<div class="error-banner">{{ error }}</div>
|
|
{% endif %}
|
|
|
|
<form action="/convert" method="post" enctype="multipart/form-data">
|
|
<div id="duos">
|
|
<div class="duo">
|
|
<button type="button" class="remove-duo" title="Remove this pair" aria-label="Remove this pair">×</button>
|
|
<div class="dropzones">
|
|
<div class="dropzone" data-zone="sdr">
|
|
<span class="tag">SDR fallback</span>
|
|
<div class="hint">.jpg / .jpeg</div>
|
|
<div class="filename"></div>
|
|
<input type="file" name="sdr[]" accept=".jpg,.jpeg" required>
|
|
</div>
|
|
<div class="dropzone" data-zone="hdr">
|
|
<span class="tag">HDR export</span>
|
|
<div class="hint">.jpg (gain map), or 32-bit float .tif</div>
|
|
<div class="filename"></div>
|
|
<input type="file" name="hdr[]" accept=".jpg,.jpeg,.tif,.tiff" required>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<button type="button" class="add-duo" id="add-duo">+ Add another pair</button>
|
|
|
|
<label class="checkbox-row">
|
|
<input type="checkbox" name="ignore_ig_resolution">
|
|
Process anyway if the resolution doesn't match Instagram's feed sizes
|
|
</label>
|
|
|
|
<button class="run" type="submit">Assemble the HDR</button>
|
|
</form>
|
|
</div>
|
|
|
|
<p class="footnote">
|
|
Each pair's files must have identical dimensions. By default that must also match one of
|
|
Instagram's feed resolutions exactly: <strong>1080x1080</strong> (1:1),
|
|
<strong>1080x1350</strong> (4:5), or <strong>1080x566</strong> (1.91:1); check the box above
|
|
to skip that check for results meant for somewhere other than Instagram. Assembling more
|
|
than one pair downloads as a <code>.zip</code>. HDR can be a regular gain-map JPEG or
|
|
Lightroom's 32-bit float linear HDR TIFF export; a TIFF HDR file gives a more precise result
|
|
than the JPEG gain-map route.
|
|
</p>
|
|
<p class="version">Instameex v{{ app_version }}</p>
|
|
<div class="repo-links">
|
|
<a href="https://git.djeex.fr/Djeex/instameex" target="_blank" rel="noopener">
|
|
<span class="icon"><img src="{{ url_for('static', filename='img/gitea.svg') }}" alt=""></span>
|
|
Gitea
|
|
</a>
|
|
<a href="https://github.com/Djeex/instameex" target="_blank" rel="noopener">
|
|
<span class="icon"><img src="{{ url_for('static', filename='img/github.svg') }}" alt=""></span>
|
|
GitHub
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
(function () {
|
|
var duosContainer = document.getElementById('duos');
|
|
var addBtn = document.getElementById('add-duo');
|
|
|
|
function updateFilename(zone) {
|
|
var input = zone.querySelector('input[type="file"]');
|
|
var filenameEl = zone.querySelector('.filename');
|
|
if (input.files && input.files.length > 0) {
|
|
zone.classList.add('has-file');
|
|
filenameEl.textContent = input.files[0].name;
|
|
filenameEl.style.display = 'block';
|
|
} else {
|
|
zone.classList.remove('has-file');
|
|
filenameEl.style.display = 'none';
|
|
}
|
|
}
|
|
|
|
duosContainer.addEventListener('change', function (e) {
|
|
var zone = e.target.closest('.dropzone');
|
|
if (zone) updateFilename(zone);
|
|
});
|
|
|
|
['dragover', 'dragenter'].forEach(function (evt) {
|
|
duosContainer.addEventListener(evt, function (e) {
|
|
var zone = e.target.closest('.dropzone');
|
|
if (zone) { e.preventDefault(); zone.classList.add('has-file'); }
|
|
});
|
|
});
|
|
|
|
duosContainer.addEventListener('click', function (e) {
|
|
if (!e.target.classList.contains('remove-duo')) return;
|
|
var duos = duosContainer.querySelectorAll('.duo');
|
|
if (duos.length > 1) {
|
|
e.target.closest('.duo').remove();
|
|
}
|
|
});
|
|
|
|
addBtn.addEventListener('click', function () {
|
|
var clone = duosContainer.querySelector('.duo').cloneNode(true);
|
|
clone.querySelectorAll('input[type="file"]').forEach(function (input) { input.value = ''; });
|
|
clone.querySelectorAll('.filename').forEach(function (el) {
|
|
el.textContent = '';
|
|
el.style.display = 'none';
|
|
});
|
|
clone.querySelectorAll('.dropzone').forEach(function (zone) { zone.classList.remove('has-file'); });
|
|
duosContainer.appendChild(clone);
|
|
});
|
|
})();
|
|
</script>
|
|
</body>
|
|
</html>
|