Use Case: Image Processing Pipeline

Use the Photo Editor as an embedded image processing widget — load images, apply filter chains, and export results, all controlled from the parent page.
This demo shows how to build a custom image filter toolbar on top of the embedded Photo Editor.

Live Demo

<iframe id="ip-demo" src="/online/webapp/photo-editor" width="100%" height="600" frameborder="0" style="border:1px solid #ccc; border-radius:4px;"></iframe>
<script>window._wsConnect('ip-demo', 'ipSocket');</script>
<div style="padding:12px 0; display:flex; flex-wrap:wrap; gap:6px; align-items:center;">

Presets:





</div><div style="padding:6px 0; display:flex; flex-wrap:wrap; gap:6px; align-items:center;">

Effects:





</div><div style="padding:6px 0; display:flex; flex-wrap:wrap; gap:6px; align-items:center;">

Transform:






</div><div style="padding:6px 0; display:flex; flex-wrap:wrap; gap:6px; align-items:center;">

Export:


</div><img id="ip-preview" style="max-width:300px;margin:8px 0;display:none;border:1px solid #ddd;border-radius:4px;"><pre id="ip-info" style="background:#f6f8fa;padding:8px;font-size:12px;display:inline-block;min-height:1em;"></pre>


What This Demo Shows

A fully custom image editing UI built on top of the Photo Editor widget:

All buttons are simple socket.fire() calls — the Photo Editor handles all the pixel processing.

Building This in Your App

<!DOCTYPE html>
<html>
<head><title>My Image Editor</title></head>
<body>
    <div id="toolbar">
        <button id="vintage">Vintage</button>
        <button id="bw">Black & White</button>
        <button id="undo">Undo</button>
        <button id="download">Download</button>
    </div>
    <iframe id="editor" src="https://sgapps.io/online/webapp/photo-editor"
        width="100%" height="600" frameborder="0"></iframe>

    <script src="https://sgapps.io/components/application-prototype/ApplicationPrototype.js"></script>
    <script src="https://sgapps.io/components/window-socket/index.js"></script>
    <script>
        var socket = new WindowSocket();
        socket.start();
        var ready = false;
        socket.on("webapp::connection::ping", function () {
            ready = true;
            socket.fire("webapp::instance::embed-mode", true);
        });

        function req(event) {
            if (!ready) return;
            var args = Array.prototype.slice.call(arguments);
            socket.fire.apply(socket, ["webapp::instance::request"].concat(args));
        }

        document.getElementById('vintage').onclick = function () {
            req("history:save");
            req("applyFilters", [
                { name: "sepia", params: { level: 0.5 } },
                { name: "hsl-adjustment", params: { hue: -30, saturation: 40, lightness: 0 } }
            ]);
        };

        document.getElementById('bw').onclick = function () {
            req("history:save");
            req("applyFilters", [
                { name: "grayscale", params: { level: 1 } },
                { name: "contrast", params: { level: 0.5 } }
            ]);
        };

        document.getElementById('undo').onclick = function () {
            req("history:undo");
        };

        document.getElementById('download').onclick = function () {
            req("getDataBase64", "image/png", function (err, dataUrl) {
                var a = document.createElement("a");
                a.href = dataUrl;
                a.download = "edited.png";
                a.click();
            });
        };
    </script>
</body>
</html>
sgapps.io