Commit 986c6c14 authored by Laureline Nevin's avatar Laureline Nevin ⌨️
Browse files

export worker now takes exportParams into account

parent c90ee20c
Loading
Loading
Loading
Loading
+4 −4
Changes for index.html: 4 added lines, 4 removed lines.
Original line number Diff line number Diff line
@@ -95,10 +95,6 @@
                    @click="fn.resetControls"></button>
            <label for="button-reset-controls" v-t="controls.reset"></label>
        </span>
        <span v-show="phase === 'render'">
            <button id="button-export" class="btn-dark btn-icon" @click="fn.setExportMode" v-icon="export"></button>
            <label for="button-export" v-t="export.button"></label>
        </span>
        <div class="export-panel" v-show="phase === 'export'">
            <span>X: </span>
            <span>{{ Math.round(exportParams.area.x) }}</span>
@@ -119,6 +115,10 @@
            <span>To full</span>
            <button v-icon="zoom-fit" @click="fn.setExportParams('full')"></button>
        </div>
        <span v-show="phase === 'render' || phase === 'export'">
            <button id="button-export" class="btn-dark btn-icon" @click="fn.exportImage" v-icon="export"></button>
            <label for="button-export" v-t="export.button"></label>
        </span>
        <div class="description-container">
            <div v-if="description">
                <h3 v-t="controls.description"></h3>
+27 −25
Changes for src/app.ts: 27 added lines, 25 removed lines.
Original line number Diff line number Diff line
@@ -6,7 +6,7 @@ import {
    resizeCanvasToDisplaySize,
    SHADER_UPDATE_EVENT,
    shaderUpdateNotify,
    WebGLCanvasRenderingContext
    WebGLCanvasRenderingContext,
} from './gl-program.ts';
import { ControlUpdateEvent, getStateDefaults, LIGHT_ANGLE_DEFAULTS, State } from './control.ts';
import {
@@ -207,7 +207,6 @@ export class App {
                    this.submitCreateMemoryDataset,
                    this.cancelCreateMemoryDataset,
                    this.onCreateMemoryFileInput,
                    this.setExportMode,
                    this.exportImage,
                    this.onExportDialogClose,
                    this.downloadExportImage,
@@ -244,7 +243,7 @@ export class App {
    static get DEFAULT_EXPORT_PARAMS() {
        return {
            area: new Rect(0, 0, 0, 0),
            zoom: 1,
            dezoom: 0,
            outerGrab: new Rect(0, 0, 0, 0),
            innerGrab: new Rect(0, 0, 0, 0),
        };
@@ -683,17 +682,6 @@ export class App {
        console.debug('Calculated max render size', this.maxCanvasSize);
    }

    private setExportMode() {
        if (this.rx.phase !== 'render' || !this.maxCanvasSize) return;
        const source = this.source;
        if (!source) return;
        this.rx.phase = 'export';
        if (this.rx.exportParams.area.w === 0 || this.rx.exportParams.area.h === 0) {
            this.setExportParams();
        }
        this.requestRender();
    }

    private setExportParams(from?: 'view' | 'full' | 'auto') {
        const source = this.source;
        if (!source) return;
@@ -709,20 +697,17 @@ export class App {
            const bl = this.state.viewport.clipToTexture([-1, -1]);
            let area = Rect.fromCorners(vec2.floor(tr, tr), vec2.ceil(bl, bl));
            area = area.intersection(canvas)!;
            let zoom = Math.pow(
                2,
                Math.max(-source.zoomDepth, Math.min(0, Math.ceil(Math.log2(this.state.viewport.zoom)))),
            );
            let dezoom = Math.max(-source.zoomDepth, Math.min(0, Math.ceil(Math.log2(this.state.viewport.zoom))));
            this.rx.exportParams = {
                area,
                zoom,
                dezoom,
                outerGrab: area,
                innerGrab: area,
            };
        } else if (from === 'full') {
            this.rx.exportParams = {
                area: canvas,
                zoom: 1,
                dezoom: 0,
                outerGrab: canvas,
                innerGrab: canvas,
            };
@@ -731,16 +716,31 @@ export class App {
    }

    private exportImage() {
        const dataset = this.currentDataset?.data;
        if (!dataset || !this.source) return;
        const source = this.source;
        if (!source || !this.currentDataset || !this.maxCanvasSize) return;
        if (this.rx.phase === 'render') {
            this.rx.phase = 'export';
            if (this.rx.exportParams.area.w === 0 || this.rx.exportParams.area.h === 0) {
                this.setExportParams();
            }
            this.requestRender();
        } else if (this.rx.phase === 'export') {
            const dataset = this.currentDataset.data;
            const exportedState = exportValues(this.state);
            const data: ExportWorkerData = {
                ...exportedState,
                lightSource: getLightSourceVec(exportedState),
            renderArea: this.source.totalSize,
            exportParams: null,
                renderArea: source.totalSize,
                exportParams: this.rx.raw().exportParams,
                dataset,
            };
            let dezoom = 0;
            while (
                data.exportParams.area.w / Math.pow(2, dezoom) > this.maxCanvasSize[0] ||
                data.exportParams.area.h / Math.pow(2, dezoom) > this.maxCanvasSize[1]
            )
                dezoom += 1;
            data.exportParams.dezoom = dezoom;
            this.source = null;
            DownloadManager.withProgressBar<Blob>(
                async (prog) =>
@@ -748,9 +748,9 @@ export class App {
                        const worker = new Worker(exporterUrl, { type: 'module' });

                        worker.onmessage = (m: MessageEvent<ExportWorkerResult>) => {
                        console.debug('Worker returned:', m.data);
                            const type = m.data.type;
                            if (type === 'finished') {
                                console.debug('Worker returned:', m.data);
                                res(m.data.imageBlob);
                            } else if (type === 'progress') {
                                const valMax = m.data.status.valueMax || [0, undefined];
@@ -776,6 +776,7 @@ export class App {
                .catch(catchError(false))
                .finally(() => this.setDataset(this.lastDataset));
        }
    }

    public onExportDialogClose(exportImg: HTMLImageElement) {
        URL.revokeObjectURL(exportImg.src);
@@ -807,6 +808,7 @@ export class App {
     * @param qx horizontal coordinate of the quadrant
     * @param qy vertical coordinate of the quadrant
     * @param value position to set the given quadrant to
     // * @param keepRatio whether aspect ratio should be kept unmodified by the operation
     */
    private setExportWindowQuadrant([qx, qy]: [0 | 1 | 2, 0 | 1 | 2], value: vec2) {
        if (!this.source) return;
+4 −2
Changes for src/dataset.ts: 4 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -159,8 +159,10 @@ export class TiledDataset extends Dataset {

    constructor(data: OptionalType<TiledDataset>, resolve?: string | URL) {
        super(data);
        this.dziURL = new URL(data.dziURL, resolve ?? window.location.toString()).href;
        this.normalsURL = new URL(data.normalsURL, resolve ?? window.location.toString()).href;
        if (!resolve && !(typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope))
            resolve = window?.location?.toString();
        this.dziURL = new URL(data.dziURL, resolve).href;
        this.normalsURL = new URL(data.normalsURL, resolve).href;
        this.dziData = data.dziData;
    }

+30 −7
Changes for src/gl-program.ts: 30 added lines, 7 removed lines.
Original line number Diff line number Diff line
@@ -6,14 +6,14 @@ import exportRectVtxSource from './shaders/exportRect.vert';
import exportRectFrgSource from './shaders/exportRect.frag';
import { mat4, vec2, vec3 } from 'gl-matrix';
import { Controls, CONTROLS_SET_UNIFORMS, State } from './control.ts';
import { DEBUG, Exported, GL } from './utils.ts';
import { DEBUG, Exported, GL, roundTo } from './utils.ts';
import { Rect, TextureSource, TextureTile } from './tiling.ts';
import { ExportParams } from './app.ts';

export type RenderData = Exported<State> & {
    readonly lightSource: Readonly<vec3>;
    readonly renderArea: [number, number];
    readonly exportParams: ExportParams | null;
    readonly exportParams: Exported<ExportParams> | null;
};

export type WebGLCanvasRenderingContext = WebGLRenderingContext & { canvas: HTMLCanvasElement };
@@ -306,12 +306,35 @@ export class RelightProgram extends GLProgramBase<
        return output;
    }

    public renderArea(source: TextureSource, data: RenderData, area: Rect) {
    public renderArea(source: TextureSource, data: RenderData, area: Rect, zoom: number) {
        super.render(data);
        const wScale = (2 * area.w) / source.totalSize[0] / this.gl.drawingBufferWidth,
            hScale = (2 * area.h) / source.totalSize[1] / this.gl.drawingBufferHeight,
            proj = mat4.fromScaling(mat4.create(), [wScale, hScale, 1]);
        mat4.translate(proj, proj, [-area.x, -area.y, 0]);
        const wScale = zoom * 2 / this.gl.drawingBufferWidth,
            hScale = zoom * 2 / this.gl.drawingBufferHeight,
            proj = mat4.fromScaling(mat4.create(), [wScale, hScale, 1]),
            offset = [-area.x - area.w / 2, -area.y - area.h / 2, 0] as const;
        mat4.translate(proj, proj, offset);
        const points: vec2[] = [
            [0, 0],
            [0.5, 0.5],
            [1, 1],
        ];
        console.debug(
            'Projection:',
            proj,
            [wScale, hScale],
            'area',
            area,
            'canvas',
            [this.gl.drawingBufferWidth, this.gl.drawingBufferHeight],
            'offset',
            offset,
            points
                .map((p) => [p[0] * area.w + area.x, p[1] * area.h + area.y] as vec2)
                .map((p): [vec2, vec2] => [p, vec2.transformMat4([0, 0], p, proj)])
                .map(([p1, p2]) =>
                    `  [${roundTo(p1, 3).join(', ')}] => [${roundTo(p2, 3).join(', ')}]`)
                .join('\n'),
        );
        this.renderWithProj(source, proj, data);
    }

+6 −1
Changes for src/main.ts: 6 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -3,7 +3,12 @@ import { DownloadManager } from './download.ts';
import en from './lang/en.yaml'; // Import translation YAMLs here to avoid transitively inclucing them in Worker code
import fr from './lang/fr.yaml';
import { createApp } from 'petite-vue';
import { catchError } from './utils.ts';
import { catchError, DEBUG } from './utils.ts';
import * as mat from 'gl-matrix';

if (DEBUG){
    (window as any).glMat = mat;
}

DownloadManager.setBar(document.querySelector('progress#load-progress') as HTMLProgressElement);

Loading