-
-
+
+
[ NO IMAGE LOADED ]
@@ -181,7 +180,6 @@ const go = $('go');
const dl = $('dl');
const dlbtn = $('dlbtn');
const statusEl = $('status');
-const hint = $('hint');
const reset = $('reset');
const srcImg = $('src');
const outImg = $('out');
@@ -201,17 +199,12 @@ const cropMarginWrap = $('cropMarginWrap');
const ctlAuto = $('ctl-auto');
const ctlPrompt = $('ctl-prompt');
-const tabOriginal= $('tabOriginal');
-const tabResult = $('tabResult');
+const tabInput = $('tabInput');
+const tabOutput = $('tabOutput');
let selectedFile = null;
let mode = 'auto';
-const HINTS = {
- auto: 'Large or busy scenes segment best with HR at 2048+. The general model expects a clear single subject at 1024.',
- prompt: 'Type what to keep, e.g. "the dog" (or several: "cow. person."). Lower the box threshold to detect more / fainter objects.',
-};
-
/* ---- mode ---- */
function setGroupEnabled(group, enabled) {
group.classList.toggle('disabled', !enabled);
@@ -222,7 +215,6 @@ function setMode(m) {
setGroupEnabled(ctlAuto, m === 'auto');
setGroupEnabled(ctlPrompt, m === 'prompt');
go.textContent = m === 'auto' ? 'REMOVE BACKGROUND' : 'SEGMENT';
- hint.textContent = HINTS[m];
}
document.querySelectorAll('input[name="mode"]').forEach(r =>
r.addEventListener('change', () => setMode(r.value)));
@@ -248,7 +240,7 @@ wireSlider(boxThr, $('boxThrVal'), v => (+v).toFixed(2));
wireSlider(textThr, $('textThrVal'), v => (+v).toFixed(2));
wireSlider(maskOffset, $('maskOffsetVal'), v => (v > 0 ? '+' : '') + v);
wireSlider(maskBlur, $('maskBlurVal'), v => String(v));
-wireSlider(cropMargin, $('cropMarginVal'), v => (+v).toFixed(1) + ' IN');
+wireSlider(cropMargin, $('cropMarginVal'), v => (+v).toFixed(2));
function syncCrop() {
cropMarginWrap.classList.toggle('disabled', !cropChk.checked);
@@ -265,17 +257,17 @@ function setStatus(msg, isErr) {
function refreshTabs() {
const hasSrc = !!srcImg.getAttribute('src');
const hasOut = !!outImg.getAttribute('src');
- tabOriginal.disabled = !hasSrc;
- tabResult.disabled = !hasOut;
+ tabInput.disabled = !hasSrc;
+ tabOutput.disabled = !hasOut;
noPreview.hidden = hasSrc || hasOut;
}
function showView(v) {
- if ((v === 'original' && tabOriginal.disabled) ||
- (v === 'result' && tabResult.disabled)) return;
- tabOriginal.classList.toggle('active', v === 'original');
- tabResult.classList.toggle('active', v === 'result');
- srcImg.hidden = v !== 'original';
- outImg.hidden = v !== 'result';
+ if ((v === 'input' && tabInput.disabled) ||
+ (v === 'output' && tabOutput.disabled)) return;
+ tabInput.classList.toggle('active', v === 'input');
+ tabOutput.classList.toggle('active', v === 'output');
+ srcImg.hidden = v !== 'input';
+ outImg.hidden = v !== 'output';
}
document.querySelectorAll('.preview-tab').forEach(t =>
t.addEventListener('click', () => showView(t.dataset.view)));
@@ -303,7 +295,7 @@ function pickFile(file) {
go.disabled = false;
setStatus('');
refreshTabs();
- showView('original');
+ showView('input');
}
fileInput.addEventListener('change', e => pickFile(e.target.files[0]));
@@ -326,8 +318,8 @@ reset.addEventListener('click', () => {
dlbtn.disabled = true;
setStatus('');
refreshTabs();
- tabOriginal.classList.add('active');
- tabResult.classList.remove('active');
+ tabInput.classList.add('active');
+ tabOutput.classList.remove('active');
});
function fileToBase64(file) {
@@ -366,11 +358,13 @@ lightbox.addEventListener('mousedown', e => {
});
document.addEventListener('keydown', e => {
if (e.key === 'Escape' && !lightbox.hidden) closeLightbox();
- if ((e.key === 'b' || e.key === 'B') && !e.metaKey && !e.ctrlKey && !e.altKey) {
- const t = e.target;
- if (t && (t.tagName === 'INPUT' || t.tagName === 'TEXTAREA' || t.tagName === 'SELECT')) return;
- toggleSidebar();
- }
+ if (e.metaKey || e.ctrlKey || e.altKey) return;
+ const t = e.target;
+ if (t && (t.tagName === 'INPUT' || t.tagName === 'TEXTAREA' || t.tagName === 'SELECT')) return;
+ const k = e.key.toLowerCase();
+ if (k === 'b') toggleSidebar();
+ else if (k === 'i') showView('input');
+ else if (k === 'o') showView('output');
});
lbStage.addEventListener('wheel', e => {
@@ -448,7 +442,7 @@ go.addEventListener('click', async () => {
dl.download = selectedFile.name.replace(/\.[^.]+$/, '') + '.png';
dlbtn.disabled = false;
refreshTabs();
- showView('result');
+ showView('output');
const secs = ((performance.now() - t0) / 1000).toFixed(1);
if (mode === 'auto') {
setStatus(`DONE — ${data.width}×${data.height} · ${data.model} @ ${data.resolution} · ${secs}S`);
diff --git a/src/rmbg_as_a_service/static/styles.css b/src/rmbg_as_a_service/static/styles.css
index 6c65f70..60c5104 100644
--- a/src/rmbg_as_a_service/static/styles.css
+++ b/src/rmbg_as_a_service/static/styles.css
@@ -768,11 +768,11 @@ select option {
pointer-events: none;
}
-/* breathing room between stacked controls inside the OUTPUT drawer */
+/* stack OUTPUT-drawer controls with the same 5px rhythm as .control-group */
.drawer-content {
display: flex;
flex-direction: column;
- gap: 14px;
+ gap: 5px;
}
/* --- help tooltip (carried over, restyled brutalist) --- */
@@ -800,7 +800,7 @@ select option {
.help:hover::after {
content: attr(data-tip);
position: absolute;
- bottom: 150%;
+ top: 150%;
right: 0;
width: 220px;
background: #000000;
@@ -866,15 +866,6 @@ select option {
color: #ff6b6b;
}
-.hint {
- font-size: 11px;
- color: #5a7a5a;
- line-height: 1.6;
- text-transform: none;
- border-left: 2px solid #2e3e2e;
- padding-left: 8px;
-}
-
/* --- preview area --- */
.preview-tabs {
position: absolute;