Spaces:
Running
Running
| <script setup lang="ts"> | |
| import { computed, ref } from "vue"; | |
| import type { InspectorControls, ModelGroup } from "../lib/types"; | |
| const props = defineProps<{ | |
| controls: InspectorControls; | |
| onnxVersionText: string; | |
| statusText: string; | |
| statusTone: string; | |
| modelStatusLabel: string; | |
| modelStatusMeta: string; | |
| imageStatusText: string; | |
| predefinedModelGroups: ModelGroup[]; | |
| isRunning: boolean; | |
| isModelLoading: boolean; | |
| }>(); | |
| const emit = defineEmits<{ | |
| modelFile: [file: File | null]; | |
| imageFile: [file: File | null]; | |
| reload: []; | |
| run: []; | |
| cancel: []; | |
| reset: []; | |
| }>(); | |
| const modelInputRef = ref<HTMLInputElement | null>(null); | |
| const imageInputRef = ref<HTMLInputElement | null>(null); | |
| const controlsDisabled = computed(() => props.isRunning || props.isModelLoading); | |
| function openModelPicker() { | |
| modelInputRef.value?.click(); | |
| } | |
| function openImagePicker() { | |
| imageInputRef.value?.click(); | |
| } | |
| function handleModelChange(event: Event) { | |
| const input = event.target as HTMLInputElement; | |
| emit("modelFile", input.files?.[0] || null); | |
| input.value = ""; | |
| } | |
| function handleImageChange(event: Event) { | |
| const input = event.target as HTMLInputElement; | |
| emit("imageFile", input.files?.[0] || null); | |
| input.value = ""; | |
| } | |
| </script> | |
| <template> | |
| <aside class="w-full lg:w-80 lg:shrink-0"> | |
| <section class="flex flex-col gap-3 rounded-xl border border-stone-300 bg-white p-4 shadow-sm"> | |
| <div class="flex flex-col gap-2"> | |
| <div class="flex items-start justify-between gap-3"> | |
| <div> | |
| <h1 class="m-0 text-lg font-semibold text-stone-900">ONNX in Browser</h1> | |
| <div class="mt-1 text-[11px] text-stone-500">{{ onnxVersionText }}</div> | |
| </div> | |
| <button | |
| type="button" | |
| class="shrink-0 text-[11px] font-normal text-stone-500 underline decoration-stone-300 underline-offset-2 transition hover:text-stone-700 disabled:cursor-not-allowed disabled:text-stone-300 disabled:decoration-stone-200" | |
| :disabled="controlsDisabled" | |
| @click="emit('reset')" | |
| > | |
| Reset | |
| </button> | |
| </div> | |
| <div | |
| :class="[ | |
| 'w-full px-3 py-2 text-center text-xs font-medium select-none', | |
| statusTone === 'success' && 'bg-emerald-100 text-emerald-900', | |
| statusTone === 'error' && 'bg-rose-100 text-rose-900', | |
| statusTone === 'busy' && 'bg-amber-100 text-amber-900', | |
| !statusTone && 'bg-stone-100 text-stone-600', | |
| ]" | |
| > | |
| {{ statusText }} | |
| </div> | |
| <button | |
| v-if="!isRunning" | |
| type="button" | |
| class="inline-flex w-full items-center justify-center rounded-md bg-stone-900 px-3.5 py-2.5 text-sm font-semibold text-white transition hover:bg-stone-800 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-stone-500 disabled:cursor-not-allowed disabled:bg-stone-300 disabled:text-stone-500" | |
| :disabled="isModelLoading" | |
| @click="emit('run')" | |
| > | |
| Run | |
| </button> | |
| <button | |
| v-else | |
| type="button" | |
| class="inline-flex w-full items-center justify-center rounded-md bg-stone-700 px-3.5 py-2.5 text-sm font-semibold text-white transition hover:bg-stone-600 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-stone-500 disabled:cursor-not-allowed disabled:bg-stone-300 disabled:text-stone-500" | |
| @click="emit('cancel')" | |
| > | |
| Cancel | |
| </button> | |
| </div> | |
| <div class="flex flex-col gap-2.5"> | |
| <label class="flex flex-col gap-1"> | |
| <span class="text-xs font-medium text-stone-600">Model</span> | |
| <div class="relative"> | |
| <select | |
| v-model="props.controls.selectedPredefinedModelId" | |
| :disabled="controlsDisabled" | |
| class="w-full appearance-none rounded-lg border border-stone-300 bg-white px-3 py-2 pr-11 text-sm text-stone-800 outline-none transition focus:border-stone-500 disabled:cursor-not-allowed disabled:opacity-60" | |
| > | |
| <option value="">-- Select a model or choose a file --</option> | |
| <optgroup | |
| v-for="group in predefinedModelGroups" | |
| :key="group.label" | |
| :label="group.label" | |
| > | |
| <option | |
| v-for="option in group.options" | |
| :key="option.value" | |
| :value="option.value" | |
| > | |
| {{ option.label }} | |
| </option> | |
| </optgroup> | |
| </select> | |
| <svg | |
| class="pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-stone-500" | |
| viewBox="0 0 16 16" | |
| fill="none" | |
| aria-hidden="true" | |
| > | |
| <path d="M4 6l4 4 4-4" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" /> | |
| </svg> | |
| </div> | |
| </label> | |
| <label class="flex flex-col gap-1"> | |
| <span class="flex w-full items-center justify-between gap-2 text-xs font-medium text-stone-600"> | |
| <span>Model file</span> | |
| <a | |
| class="font-normal text-stone-500 underline decoration-stone-300 underline-offset-2 transition hover:text-stone-700" | |
| href="https://huggingface.co/spaces/notaneimu/pth2onnx-converter" | |
| target="_blank" | |
| rel="noopener noreferrer" | |
| > | |
| Convert from pth | |
| </a> | |
| </span> | |
| <div class="flex flex-col gap-1.5"> | |
| <input | |
| ref="modelInputRef" | |
| class="sr-only" | |
| type="file" | |
| accept=".onnx,application/octet-stream" | |
| :disabled="controlsDisabled" | |
| @change="handleModelChange" | |
| /> | |
| <button | |
| type="button" | |
| class="inline-flex w-full items-center justify-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-stone-900 ring-1 ring-inset ring-stone-300 transition hover:bg-stone-50 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-stone-400 disabled:cursor-not-allowed disabled:bg-stone-100 disabled:text-stone-400" | |
| :disabled="controlsDisabled" | |
| @click="openModelPicker" | |
| > | |
| Choose model file | |
| </button> | |
| </div> | |
| </label> | |
| <div class="flex min-w-0 flex-col gap-0.5 rounded-xl border border-stone-300 bg-stone-50 px-3 py-2.5"> | |
| <span class="min-w-0 break-words text-sm font-semibold text-stone-900">{{ modelStatusLabel }}</span> | |
| <span class="min-w-0 break-words text-[11px] text-stone-600">{{ modelStatusMeta }}</span> | |
| </div> | |
| <div class="flex flex-col gap-2.5"> | |
| <label class="flex items-center justify-between rounded-lg border border-stone-200 bg-stone-50 px-3 py-2"> | |
| <span class="text-xs font-medium text-stone-600">Auto loading</span> | |
| <input | |
| v-model="props.controls.autoLoadModel" | |
| type="checkbox" | |
| :disabled="controlsDisabled" | |
| class="h-4 w-4 accent-stone-700 disabled:opacity-60" | |
| /> | |
| </label> | |
| <button | |
| type="button" | |
| class="inline-flex w-full items-center justify-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-stone-900 ring-1 ring-inset ring-stone-300 transition hover:bg-stone-50 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-stone-400 disabled:cursor-not-allowed disabled:bg-stone-100 disabled:text-stone-400" | |
| :disabled="controlsDisabled" | |
| @click="emit('reload')" | |
| > | |
| Load model | |
| </button> | |
| </div> | |
| <label class="flex flex-col gap-1"> | |
| <span class="text-xs font-medium text-stone-600">Image</span> | |
| <div class="flex flex-col gap-1.5"> | |
| <input | |
| ref="imageInputRef" | |
| class="sr-only" | |
| type="file" | |
| accept="image/*" | |
| :disabled="controlsDisabled" | |
| @change="handleImageChange" | |
| /> | |
| <button | |
| type="button" | |
| class="inline-flex w-full items-center justify-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-stone-900 ring-1 ring-inset ring-stone-300 transition hover:bg-stone-50 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-stone-400 disabled:cursor-not-allowed disabled:bg-stone-100 disabled:text-stone-400" | |
| :disabled="controlsDisabled" | |
| @click="openImagePicker" | |
| > | |
| Choose image file | |
| </button> | |
| <p class="m-0 min-h-4 text-xs text-stone-500">{{ imageStatusText }}</p> | |
| </div> | |
| </label> | |
| <label class="flex flex-col gap-1"> | |
| <span class="text-xs font-medium text-stone-600">Execution provider</span> | |
| <div class="relative"> | |
| <select | |
| v-model="props.controls.provider" | |
| :disabled="controlsDisabled" | |
| class="w-full appearance-none rounded-lg border border-stone-300 bg-white px-3 py-2 pr-11 text-sm text-stone-800 outline-none transition focus:border-stone-500 disabled:cursor-not-allowed disabled:opacity-60" | |
| > | |
| <option value="webgpu">WebGPU (default)</option> | |
| <option value="wasm">WASM</option> | |
| <option value="webgl">WebGL</option> | |
| </select> | |
| <svg | |
| class="pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-stone-500" | |
| viewBox="0 0 16 16" | |
| fill="none" | |
| aria-hidden="true" | |
| > | |
| <path d="M4 6l4 4 4-4" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" /> | |
| </svg> | |
| </div> | |
| </label> | |
| <label class="flex flex-col gap-1"> | |
| <span class="text-xs font-medium text-stone-600">Tile size</span> | |
| <input | |
| v-model="props.controls.tileSize" | |
| type="number" | |
| min="1" | |
| step="1" | |
| placeholder="(empty disables tiling)" | |
| :disabled="controlsDisabled" | |
| class="w-full rounded-lg border border-stone-300 bg-white px-3 py-2 text-sm text-stone-800 outline-none transition focus:border-stone-500 disabled:cursor-not-allowed disabled:opacity-60" | |
| /> | |
| </label> | |
| <label class="flex items-center justify-between rounded-lg border border-stone-200 bg-stone-50 px-3 py-2"> | |
| <span class="text-xs font-medium text-stone-600">Tile blending</span> | |
| <input | |
| v-model="props.controls.tileBlendingEnabled" | |
| type="checkbox" | |
| :disabled="controlsDisabled" | |
| class="h-4 w-4 accent-stone-700 disabled:opacity-60" | |
| /> | |
| </label> | |
| <label class="flex flex-col gap-1"> | |
| <span class="text-xs font-medium text-stone-600">Initial width</span> | |
| <input | |
| v-model="props.controls.width" | |
| type="number" | |
| min="1" | |
| step="1" | |
| placeholder="auto" | |
| :disabled="controlsDisabled" | |
| class="w-full rounded-lg border border-stone-300 bg-white px-3 py-2 text-sm text-stone-800 outline-none transition focus:border-stone-500 disabled:cursor-not-allowed disabled:opacity-60" | |
| /> | |
| </label> | |
| <label class="flex flex-col gap-1"> | |
| <span class="text-xs font-medium text-stone-600">Initial height</span> | |
| <input | |
| v-model="props.controls.height" | |
| type="number" | |
| min="1" | |
| step="1" | |
| placeholder="auto" | |
| :disabled="controlsDisabled" | |
| class="w-full rounded-lg border border-stone-300 bg-white px-3 py-2 text-sm text-stone-800 outline-none transition focus:border-stone-500 disabled:cursor-not-allowed disabled:opacity-60" | |
| /> | |
| </label> | |
| <label class="flex flex-col gap-1"> | |
| <span class="text-xs font-medium text-stone-600">Pre resize algorithm</span> | |
| <div class="relative"> | |
| <select | |
| v-model="props.controls.preResizeAlgorithm" | |
| :disabled="controlsDisabled" | |
| class="w-full appearance-none rounded-lg border border-stone-300 bg-white px-3 py-2 pr-11 text-sm text-stone-800 outline-none transition focus:border-stone-500 disabled:cursor-not-allowed disabled:opacity-60" | |
| > | |
| <option value="lanczos">Lanczos</option> | |
| <option value="area">Area</option> | |
| <option value="bicubic">Bicubic</option> | |
| <option value="nearest">Nearest neighbor</option> | |
| </select> | |
| <svg | |
| class="pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-stone-500" | |
| viewBox="0 0 16 16" | |
| fill="none" | |
| aria-hidden="true" | |
| > | |
| <path d="M4 6l4 4 4-4" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" /> | |
| </svg> | |
| </div> | |
| <p class="m-0 text-xs italic leading-snug text-stone-500">Used when resizing the source image to the model input size.</p> | |
| </label> | |
| <label class="flex flex-col gap-1"> | |
| <span class="text-xs font-medium text-stone-600">Final scale</span> | |
| <input | |
| v-model="props.controls.outputScale" | |
| type="number" | |
| min="1" | |
| max="4" | |
| step="0.1" | |
| placeholder="off (keep model output)" | |
| :disabled="controlsDisabled" | |
| class="w-full rounded-lg border border-stone-300 bg-white px-3 py-2 text-sm text-stone-800 outline-none transition focus:border-stone-500 disabled:cursor-not-allowed disabled:opacity-60" | |
| /> | |
| <p class="m-0 text-xs italic leading-snug text-stone-500">Optional downscale after inference. Uses the input size as 1x and caps at the model output.</p> | |
| </label> | |
| <label class="flex flex-col gap-1"> | |
| <span class="text-xs font-medium text-stone-600">Post resize algorithm</span> | |
| <div class="relative"> | |
| <select | |
| v-model="props.controls.outputScaleAlgorithm" | |
| :disabled="controlsDisabled" | |
| class="w-full appearance-none rounded-lg border border-stone-300 bg-white px-3 py-2 pr-11 text-sm text-stone-800 outline-none transition focus:border-stone-500 disabled:cursor-not-allowed disabled:opacity-60" | |
| > | |
| <option value="lanczos">Lanczos</option> | |
| <option value="area">Area</option> | |
| <option value="bicubic">Bicubic</option> | |
| <option value="nearest">Nearest neighbor</option> | |
| </select> | |
| <svg | |
| class="pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-stone-500" | |
| viewBox="0 0 16 16" | |
| fill="none" | |
| aria-hidden="true" | |
| > | |
| <path d="M4 6l4 4 4-4" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" /> | |
| </svg> | |
| </div> | |
| <p class="m-0 text-xs italic leading-snug text-stone-500">Used only for the optional output resize after inference.</p> | |
| </label> | |
| <label class="flex items-center justify-between rounded-lg border border-stone-200 bg-stone-50 px-3 py-2"> | |
| <span class="text-xs font-medium text-stone-600">Compare with classic upscale</span> | |
| <input | |
| v-model="props.controls.compareWithClassicUpscale" | |
| type="checkbox" | |
| :disabled="controlsDisabled" | |
| class="h-4 w-4 accent-stone-700 disabled:opacity-60" | |
| /> | |
| </label> | |
| <label class="flex flex-col gap-1"> | |
| <span class="text-xs font-medium text-stone-600">Classic compare algorithm</span> | |
| <div class="relative"> | |
| <select | |
| v-model="props.controls.classicCompareAlgorithm" | |
| :disabled="controlsDisabled || !props.controls.compareWithClassicUpscale" | |
| class="w-full appearance-none rounded-lg border border-stone-300 bg-white px-3 py-2 pr-11 text-sm text-stone-800 outline-none transition focus:border-stone-500 disabled:cursor-not-allowed disabled:opacity-60" | |
| > | |
| <option value="lanczos">Lanczos</option> | |
| <option value="area">Area</option> | |
| <option value="bicubic">Bicubic</option> | |
| <option value="nearest">Nearest neighbor</option> | |
| </select> | |
| <svg | |
| class="pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-stone-500" | |
| viewBox="0 0 16 16" | |
| fill="none" | |
| aria-hidden="true" | |
| > | |
| <path d="M4 6l4 4 4-4" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" /> | |
| </svg> | |
| </div> | |
| <p class="m-0 text-xs italic leading-snug text-stone-500">Builds a non-AI baseline upscaled to the same final resolution as the model result.</p> | |
| </label> | |
| <details class="group"> | |
| <summary class="flex cursor-pointer list-none items-center justify-between py-1 text-sm font-semibold text-stone-700"> | |
| <span>Additional params</span> | |
| <span class="text-xs text-stone-500 group-open:hidden">▶</span> | |
| <span class="hidden text-xs text-stone-500 group-open:inline">▼</span> | |
| </summary> | |
| <div class="flex flex-col gap-2.5 pt-2"> | |
| <label class="flex items-center justify-between rounded-lg border border-stone-200 bg-stone-50 px-3 py-2"> | |
| <span class="text-xs font-medium text-stone-600">Color correct final image</span> | |
| <input | |
| v-model="props.controls.colorCorrectionEnabled" | |
| type="checkbox" | |
| :disabled="controlsDisabled" | |
| class="h-4 w-4 accent-stone-700 disabled:opacity-60" | |
| /> | |
| </label> | |
| <label class="flex flex-col gap-1"> | |
| <span class="text-xs font-medium text-stone-600">Color correction strength (%)</span> | |
| <input | |
| v-model="props.controls.colorCorrectionStrength" | |
| type="number" | |
| min="0" | |
| max="100" | |
| step="5" | |
| placeholder="100" | |
| :disabled="controlsDisabled || !props.controls.colorCorrectionEnabled" | |
| class="w-full rounded-lg border border-stone-300 bg-white px-3 py-2 text-sm text-stone-800 outline-none transition focus:border-stone-500 disabled:cursor-not-allowed disabled:opacity-60" | |
| /> | |
| <p class="m-0 text-xs italic leading-snug text-stone-500">Matches RGB color balance and black/white levels back toward the source image.</p> | |
| </label> | |
| <label class="flex flex-col gap-1"> | |
| <span class="text-xs font-medium text-stone-600">Black/white clip (%)</span> | |
| <input | |
| v-model="props.controls.colorCorrectionClip" | |
| type="number" | |
| min="0" | |
| max="10" | |
| step="0.1" | |
| placeholder="0.6" | |
| :disabled="controlsDisabled || !props.controls.colorCorrectionEnabled" | |
| class="w-full rounded-lg border border-stone-300 bg-white px-3 py-2 text-sm text-stone-800 outline-none transition focus:border-stone-500 disabled:cursor-not-allowed disabled:opacity-60" | |
| /> | |
| <p class="m-0 text-xs italic leading-snug text-stone-500">Ignores tiny outliers when matching source black and white points.</p> | |
| </label> | |
| <label class="flex items-center justify-between rounded-lg border border-stone-200 bg-stone-50 px-3 py-2"> | |
| <span class="text-xs font-medium text-stone-600">Add film grain</span> | |
| <input | |
| v-model="props.controls.filmGrainEnabled" | |
| type="checkbox" | |
| :disabled="controlsDisabled" | |
| class="h-4 w-4 accent-stone-700 disabled:opacity-60" | |
| /> | |
| </label> | |
| <label class="flex flex-col gap-1"> | |
| <span class="text-xs font-medium text-stone-600">Film grain amount (%)</span> | |
| <input | |
| v-model="props.controls.filmGrainAmount" | |
| type="number" | |
| min="0" | |
| max="100" | |
| step="1" | |
| placeholder="6" | |
| :disabled="controlsDisabled || !props.controls.filmGrainEnabled" | |
| class="w-full rounded-lg border border-stone-300 bg-white px-3 py-2 text-sm text-stone-800 outline-none transition focus:border-stone-500 disabled:cursor-not-allowed disabled:opacity-60" | |
| /> | |
| </label> | |
| <label class="flex flex-col gap-1"> | |
| <span class="text-xs font-medium text-stone-600">Film grain size (px)</span> | |
| <input | |
| v-model="props.controls.filmGrainSize" | |
| type="number" | |
| min="0.5" | |
| max="8" | |
| step="0.1" | |
| placeholder="1.2" | |
| :disabled="controlsDisabled || !props.controls.filmGrainEnabled" | |
| class="w-full rounded-lg border border-stone-300 bg-white px-3 py-2 text-sm text-stone-800 outline-none transition focus:border-stone-500 disabled:cursor-not-allowed disabled:opacity-60" | |
| /> | |
| </label> | |
| <label class="flex items-center justify-between rounded-lg border border-stone-200 bg-stone-50 px-3 py-2"> | |
| <span class="text-xs font-medium text-stone-600">Monochrome grain</span> | |
| <input | |
| v-model="props.controls.filmGrainMonochrome" | |
| type="checkbox" | |
| :disabled="controlsDisabled || !props.controls.filmGrainEnabled" | |
| class="h-4 w-4 accent-stone-700 disabled:opacity-60" | |
| /> | |
| </label> | |
| <label class="flex flex-col gap-1"> | |
| <span class="text-xs font-medium text-stone-600">Seam blend width (input px)</span> | |
| <input | |
| v-model="props.controls.seamBlendWidth" | |
| type="number" | |
| min="0" | |
| step="1" | |
| placeholder="auto" | |
| :disabled="controlsDisabled || !props.controls.tileBlendingEnabled" | |
| class="w-full rounded-lg border border-stone-300 bg-white px-3 py-2 text-sm text-stone-800 outline-none transition focus:border-stone-500 disabled:cursor-not-allowed disabled:opacity-60" | |
| /> | |
| <p class="m-0 text-xs italic leading-snug text-stone-500">Blank uses auto seam width. Set 0 to disable seam feather blending.</p> | |
| </label> | |
| <label class="flex flex-col gap-1"> | |
| <span class="text-xs font-medium text-stone-600">Seam correction strength (%)</span> | |
| <input | |
| v-model="props.controls.seamCorrectionStrength" | |
| type="number" | |
| min="0" | |
| max="300" | |
| step="5" | |
| placeholder="100" | |
| :disabled="controlsDisabled || !props.controls.tileBlendingEnabled" | |
| class="w-full rounded-lg border border-stone-300 bg-white px-3 py-2 text-sm text-stone-800 outline-none transition focus:border-stone-500 disabled:cursor-not-allowed disabled:opacity-60" | |
| /> | |
| <p class="m-0 text-xs italic leading-snug text-stone-500">0 disables exposure matching. 100 is default, higher values apply stronger correction.</p> | |
| </label> | |
| <label class="flex flex-col gap-1"> | |
| <span class="text-xs font-medium text-stone-600">Graph optimization</span> | |
| <div class="relative"> | |
| <select | |
| v-model="props.controls.optLevel" | |
| :disabled="controlsDisabled" | |
| class="w-full appearance-none rounded-lg border border-stone-300 bg-white px-3 py-2 pr-11 text-sm text-stone-800 outline-none transition focus:border-stone-500 disabled:cursor-not-allowed disabled:opacity-60" | |
| > | |
| <option value="all">All (default)</option> | |
| <option value="extended">Extended</option> | |
| <option value="basic">Basic</option> | |
| <option value="disabled">Disabled</option> | |
| </select> | |
| <svg | |
| class="pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-stone-500" | |
| viewBox="0 0 16 16" | |
| fill="none" | |
| aria-hidden="true" | |
| > | |
| <path d="M4 6l4 4 4-4" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" /> | |
| </svg> | |
| </div> | |
| </label> | |
| <label class="flex flex-col gap-1"> | |
| <span class="text-xs font-medium text-stone-600">WebGPU layout</span> | |
| <div class="relative"> | |
| <select | |
| v-model="props.controls.webgpuLayout" | |
| :disabled="controlsDisabled" | |
| class="w-full appearance-none rounded-lg border border-stone-300 bg-white px-3 py-2 pr-11 text-sm text-stone-800 outline-none transition focus:border-stone-500 disabled:cursor-not-allowed disabled:opacity-60" | |
| > | |
| <option value="NCHW">NCHW (default)</option> | |
| <option value="NHWC">NHWC</option> | |
| </select> | |
| <svg | |
| class="pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-stone-500" | |
| viewBox="0 0 16 16" | |
| fill="none" | |
| aria-hidden="true" | |
| > | |
| <path d="M4 6l4 4 4-4" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" /> | |
| </svg> | |
| </div> | |
| </label> | |
| <label class="flex flex-col gap-1"> | |
| <span class="text-xs font-medium text-stone-600">WebGPU validation</span> | |
| <div class="relative"> | |
| <select | |
| v-model="props.controls.webgpuValidation" | |
| :disabled="controlsDisabled" | |
| class="w-full appearance-none rounded-lg border border-stone-300 bg-white px-3 py-2 pr-11 text-sm text-stone-800 outline-none transition focus:border-stone-500 disabled:cursor-not-allowed disabled:opacity-60" | |
| > | |
| <option value="basic">Basic (default)</option> | |
| <option value="full">Full</option> | |
| <option value="wgpuOnly">WebGPU-only</option> | |
| <option value="disabled">Disabled</option> | |
| </select> | |
| <svg | |
| class="pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-stone-500" | |
| viewBox="0 0 16 16" | |
| fill="none" | |
| aria-hidden="true" | |
| > | |
| <path d="M4 6l4 4 4-4" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" /> | |
| </svg> | |
| </div> | |
| </label> | |
| <label class="flex flex-col gap-1"> | |
| <span class="text-xs font-medium text-stone-600">Input layout</span> | |
| <div class="relative"> | |
| <select | |
| v-model="props.controls.layout" | |
| :disabled="controlsDisabled" | |
| class="w-full appearance-none rounded-lg border border-stone-300 bg-white px-3 py-2 pr-11 text-sm text-stone-800 outline-none transition focus:border-stone-500 disabled:cursor-not-allowed disabled:opacity-60" | |
| > | |
| <option value="nchw">NCHW</option> | |
| <option value="nhwc">NHWC</option> | |
| </select> | |
| <svg | |
| class="pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-stone-500" | |
| viewBox="0 0 16 16" | |
| fill="none" | |
| aria-hidden="true" | |
| > | |
| <path d="M4 6l4 4 4-4" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" /> | |
| </svg> | |
| </div> | |
| </label> | |
| <label class="flex flex-col gap-1"> | |
| <span class="text-xs font-medium text-stone-600">Channel order</span> | |
| <div class="relative"> | |
| <select | |
| v-model="props.controls.channelOrder" | |
| :disabled="controlsDisabled" | |
| class="w-full appearance-none rounded-lg border border-stone-300 bg-white px-3 py-2 pr-11 text-sm text-stone-800 outline-none transition focus:border-stone-500 disabled:cursor-not-allowed disabled:opacity-60" | |
| > | |
| <option value="rgb">RGB</option> | |
| <option value="bgr">BGR</option> | |
| </select> | |
| <svg | |
| class="pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-stone-500" | |
| viewBox="0 0 16 16" | |
| fill="none" | |
| aria-hidden="true" | |
| > | |
| <path d="M4 6l4 4 4-4" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" /> | |
| </svg> | |
| </div> | |
| </label> | |
| <label class="flex items-center justify-between rounded-lg border border-stone-200 bg-stone-50 px-3 py-2"> | |
| <span class="text-xs font-medium text-stone-600">Scale pixels to 0..1</span> | |
| <input | |
| v-model="props.controls.normalize" | |
| type="checkbox" | |
| :disabled="controlsDisabled" | |
| class="h-4 w-4 accent-stone-700 disabled:opacity-60" | |
| /> | |
| </label> | |
| <label class="flex flex-col gap-1"> | |
| <span class="text-xs font-medium text-stone-600">Mean (comma separated)</span> | |
| <input | |
| v-model="props.controls.mean" | |
| type="text" | |
| :disabled="controlsDisabled" | |
| class="w-full rounded-lg border border-stone-300 bg-white px-3 py-2 text-sm text-stone-800 outline-none transition focus:border-stone-500 disabled:cursor-not-allowed disabled:opacity-60" | |
| /> | |
| </label> | |
| <label class="flex flex-col gap-1"> | |
| <span class="text-xs font-medium text-stone-600">Std (comma separated)</span> | |
| <input | |
| v-model="props.controls.std" | |
| type="text" | |
| :disabled="controlsDisabled" | |
| class="w-full rounded-lg border border-stone-300 bg-white px-3 py-2 text-sm text-stone-800 outline-none transition focus:border-stone-500 disabled:cursor-not-allowed disabled:opacity-60" | |
| /> | |
| </label> | |
| </div> | |
| </details> | |
| </div> | |
| </section> | |
| </aside> | |
| </template> | |