{"id":43,"date":"2026-09-09T12:57:31","date_gmt":"2026-09-09T12:57:31","guid":{"rendered":"https:\/\/ankmavenmarketing.in\/tools\/?page_id=43"},"modified":"2026-09-10T12:40:45","modified_gmt":"2026-09-10T12:40:45","slug":"online-image-editor","status":"publish","type":"page","link":"https:\/\/ankmavenmarketing.in\/tools\/online-image-editor\/","title":{"rendered":"Online Image editor"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"43\" class=\"elementor elementor-43\">\n\t\t\t\t<div class=\"elementor-element elementor-element-779c3ba e-con e-atomic-element e-flexbox-base e-f773250 \" data-id=\"779c3ba\" data-element_type=\"e-flexbox\" data-e-type=\"e-flexbox\" data-interaction-id=\"779c3ba\">\n    \t\t<div class=\"elementor-element elementor-element-2b12857 elementor-widget elementor-widget-shortcode\" data-id=\"2b12857\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"shortcode.default\">\n\t\t\t\t\t\t\t<div class=\"elementor-shortcode\">    <!-- Cropper.js & JSZip Libraries -->\r\n    <link rel=\"stylesheet\" href=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/cropperjs\/1.5.13\/cropper.min.css\"\/>\r\n    <script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/cropperjs\/1.5.13\/cropper.min.js\"><\/script>\r\n    <script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/jszip\/3.10.1\/jszip.min.js\"><\/script>\r\n    \r\n    <div id=\"ank-suite-container\">\r\n        <style>\r\n            #ank-suite-container {\r\n                --ank-dark: #070d19; --ank-navy: #0f172a; --ank-cyan: #22d3ee; --ank-orange: #f97316; \r\n                --ank-border: #1e293b; --ank-card-bg: #0b1329; --ank-text: #f8fafc; --ank-muted: #94a3b8;\r\n                font-family: 'Inter', sans-serif; background: var(--ank-dark); max-width: 1200px; margin: 5px auto;\r\n                border: 1px solid var(--ank-border); color: var(--ank-text); box-sizing: border-box; position: relative;\r\n            }\r\n            #ank-suite-container * { box-sizing: border-box; }\r\n\r\n            .ank-head { background: var(--ank-navy); padding: 10px 14px; display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid var(--ank-border); }\r\n            .ank-head h4 { color: #fff; margin: 0; font-size: 11px; letter-spacing: 2px; font-weight: 900; text-transform: uppercase; }\r\n            .ank-head h4 span { color: var(--ank-orange); }\r\n\r\n            \/* Category Toolbar Grid *\/\r\n            .ank-toolbar-grid { display: grid; grid-template-columns: repeat(4, 1fr); background: var(--ank-border); gap: 1px; border-bottom: 1px solid var(--ank-border); }\r\n            .ank-tool-category { background: var(--ank-card-bg); padding: 8px 10px; display: flex; flex-direction: column; gap: 4px; }\r\n            .ank-cat-title { font-size: 8px; font-weight: 900; color: var(--ank-orange); text-transform: uppercase; letter-spacing: 1px; border-bottom: 1px solid var(--ank-border); padding-bottom: 3px; }\r\n            \r\n            .ank-icon-row { display: flex; gap: 4px; flex-wrap: wrap; }\r\n            .ank-icon-btn { position: relative; width: 28px; height: 28px; background: var(--ank-navy); border: 1px solid var(--ank-border); border-radius: 4px; display: flex; align-items: center; justify-content: center; cursor: pointer; font-size: 11px; transition: 0.2s; color: var(--ank-text); }\r\n            .ank-icon-btn:hover { background: var(--ank-cyan); color: var(--ank-dark); border-color: var(--ank-cyan); }\r\n            .ank-icon-btn:hover::after {\r\n                content: attr(data-tooltip); position: absolute; bottom: 32px; left: 50%; transform: translateX(-50%);\r\n                background: var(--ank-navy); color: #fff; font-size: 7px; padding: 2px 5px; white-space: nowrap;\r\n                border-radius: 3px; font-weight: 700; z-index: 100; pointer-events: none; border: 1px solid var(--ank-border);\r\n            }\r\n\r\n            .ank-control-input { width: 100%; height: 28px; border: 1px solid var(--ank-border); border-radius: 3px; font-size: 9px; font-weight: 700; padding: 0 4px; outline: none; background: var(--ank-navy); color: var(--ank-text); cursor: pointer; }\r\n            .ank-control-input option { background: var(--ank-navy); color: var(--ank-text); }\r\n\r\n            \/* Workspace Viewport *\/\r\n            .ank-workspace { display: grid; grid-template-columns: 2fr 1fr; height: 380px; background: var(--ank-border); gap: 1px; }\r\n            .ank-main-viewport { background: #040810; position: relative; display: flex; align-items: center; justify-content: center; overflow: hidden; padding: 10px; background-image: radial-gradient(#1e293b 0.8px, transparent 0.8px); background-size: 12px 12px; }\r\n            .ank-main-viewport img { max-width: 100%; max-height: 100%; display: block; }\r\n            \r\n            .ank-side-panel { background: var(--ank-card-bg); display: flex; flex-direction: column; padding: 10px; justify-content: space-between; }\r\n            .ank-info-box { background: var(--ank-navy); border: 1px solid var(--ank-border); border-radius: 4px; padding: 8px; font-size: 9px; font-weight: 700; color: var(--ank-muted); line-height: 1.4; }\r\n            .ank-info-box strong { color: var(--ank-cyan); }\r\n\r\n            \/* Thumbnails Strip with Checkboxes *\/\r\n            .ank-thumbs { display: none; gap: 8px; padding: 8px 10px; background: var(--ank-card-bg); border-top: 1px solid var(--ank-border); overflow-x: auto; max-height: 110px; }\r\n            .t-card { display: flex; flex-direction: column; gap: 2px; min-width: 55px; align-items: center; }\r\n            .t-box { width: 45px; height: 45px; border: 2px solid var(--ank-border); cursor: pointer; border-radius: 4px; overflow: hidden; background: var(--ank-navy); position: relative; }\r\n            .t-box.active { border-color: var(--ank-cyan); background: #0f2238; }\r\n            .t-box img { width: 100%; height: 100%; object-fit: cover; }\r\n            .t-check { font-size: 8px; cursor: pointer; display: flex; align-items: center; gap: 2px; font-weight: 700; color: var(--ank-muted); }\r\n            .t-check input { accent-color: var(--ank-cyan); }\r\n\r\n            \/* Footer *\/\r\n            .ank-foot { padding: 8px 12px; display: flex; justify-content: space-between; align-items: center; background: var(--ank-navy); border-top: 1px solid var(--ank-border); }\r\n            .btn-main { background: var(--ank-orange); color: white; border: none; padding: 0 18px; height: 35px; font-size: 10px; font-weight: 900; cursor: pointer; text-transform: uppercase; border-radius: 4px; transition: 0.2s; }\r\n            .btn-main:hover { opacity: 0.9; }\r\n            .btn-success { background: var(--ank-cyan) !important; color: var(--ank-dark) !important; display: none; }\r\n            .btn-reset { background: var(--ank-card-bg); color: var(--ank-text); border: 1px solid var(--ank-border); }\r\n\r\n            @media (max-width: 1024px) {\r\n                .ank-toolbar-grid { grid-template-columns: repeat(2, 1fr); }\r\n                .ank-workspace { grid-template-columns: 1fr; height: 500px; }\r\n            }\r\n        <\/style>\r\n\r\n        <div class=\"ank-head\">\r\n            <h4>ANK MAVEN <span>MARKETING<\/span> \u2014 ULTIMATE IMAGE SUITE ENGINE v10.1<\/h4>\r\n            <div id=\"sys-tag\" style=\"color:var(--ank-cyan); font-size:9px; font-weight:900;\">\u25cf READY<\/div>\r\n        <\/div>\r\n\r\n        <!-- CATEGORY-WISE TOOLBAR -->\r\n        <div class=\"ank-toolbar-grid\">\r\n            <!-- CAT 1: ASPECT RATIOS -->\r\n            <div class=\"ank-tool-category\">\r\n                <div class=\"ank-cat-title\">1. Aspect Ratios (Global Sync)<\/div>\r\n                <div style=\"display:flex; flex-direction:column; gap:4px;\">\r\n                    <select id=\"suite-ratio-list\" class=\"ank-control-input\" onchange=\"applyGlobalRatio(this.value)\">\r\n                        <option value=\"NaN\">Free Custom Ratio \/ Original<\/option>\r\n                        <optgroup label=\"--- Social & Marketing ---\">\r\n                            <option value=\"1\">Square Post (1:1)<\/option>\r\n                            <option value=\"0.8\">Portrait Post (4:5)<\/option>\r\n                            <option value=\"0.5625\">Reels \/ Story \/ TikTok (9:16)<\/option>\r\n                            <option value=\"1.91\">Shared Link \/ Banner (1.91:1)<\/option>\r\n                            <option value=\"1.7777\">YouTube \/ Landscape (16:9)<\/option>\r\n                            <option value=\"2\">Twitter Header (2:1)<\/option>\r\n                        <\/optgroup>\r\n                        <optgroup label=\"--- Cinematic & Wallpapers ---\">\r\n                            <option value=\"2.3333\">Ultrawide Cinematic (21:9)<\/option>\r\n                            <option value=\"0.4615\">Mobile Wallpaper (9:19.5)<\/option>\r\n                        <\/optgroup>\r\n                        <optgroup label=\"--- Professional & Print ---\">\r\n                            <option value=\"1.3333\">Standard Photo \/ Catalog (4:3)<\/option>\r\n                            <option value=\"1.5\">DSLR \/ Web Banner (3:2)<\/option>\r\n                            <option value=\"0.707\">A4 Document (1:1.414)<\/option>\r\n                            <option value=\"1.618\">Golden Ratio (1.618:1)<\/option>\r\n                        <\/optgroup>\r\n                    <\/select>\r\n                    <div class=\"ank-icon-row\">\r\n                        <div class=\"ank-icon-btn\" data-tooltip=\"Square (1:1)\" onclick=\"applyGlobalRatio(1)\">\u2b1b<\/div>\r\n                        <div class=\"ank-icon-btn\" data-tooltip=\"Portrait (4:5)\" onclick=\"applyGlobalRatio(0.8)\">\ud83d\udcf1<\/div>\r\n                        <div class=\"ank-icon-btn\" data-tooltip=\"Landscape (16:9)\" onclick=\"applyGlobalRatio(1.777)\">\ud83d\udda5\ufe0f<\/div>\r\n                    <\/div>\r\n                <\/div>\r\n            <\/div>\r\n\r\n            <!-- CAT 2: TRANSFORM, ROTATE & HISTORY -->\r\n            <div class=\"ank-tool-category\">\r\n                <div class=\"ank-cat-title\">2. Transform & History<\/div>\r\n                <div class=\"ank-icon-row\">\r\n                    <div class=\"ank-icon-btn\" data-tooltip=\"Rotate 90\u00b0 \u21bb\" onclick=\"suiteRotate(90)\">\ud83d\udd04<\/div>\r\n                    <div class=\"ank-icon-btn\" data-tooltip=\"Flip Horizontal \u21c4\" onclick=\"suiteFlipX()\">\u21c4<\/div>\r\n                    <div class=\"ank-icon-btn\" data-tooltip=\"Undo \u21ba\" onclick=\"suiteUndo()\">\u21ba<\/div>\r\n                    <div class=\"ank-icon-btn\" data-tooltip=\"Redo \u21bb\" onclick=\"suiteRedo()\">\u21bb<\/div>\r\n                    <div class=\"ank-icon-btn\" data-tooltip=\"Reset Transform\" onclick=\"suiteReset()\">\u23f9\ufe0f<\/div>\r\n                <\/div>\r\n                <div style=\"font-size:7px; font-weight:700; margin-top:2px; color:var(--ank-muted);\">Fine Tilt: <input type=\"range\" id=\"suite-tilt\" min=\"-180\" max=\"180\" value=\"0\" oninput=\"suiteFineRotate(this.value)\" style=\"width:100%; accent-color:var(--ank-cyan);\"><\/div>\r\n            <\/div>\r\n\r\n            <!-- CAT 3: COLOR SLIDER -->\r\n            <div class=\"ank-tool-category\">\r\n                <div class=\"ank-cat-title\">3. Live Brightness Slider<\/div>\r\n                <div style=\"display:flex; flex-direction:column; gap:2px;\">\r\n                    <div style=\"font-size:7px; font-weight:700; color:var(--ank-muted);\">Bright: <input type=\"number\" id=\"inp-b\" value=\"100\" min=\"0\" max=\"200\" onchange=\"syncSuiteVal('b', this.value)\" style=\"width:32px; font-size:7px; background:var(--ank-navy); border:1px solid var(--ank-border); color:var(--ank-text);\">%<\/div>\r\n                    <input type=\"range\" id=\"sl-b\" min=\"0\" max=\"200\" value=\"100\" oninput=\"syncSuiteSlider('b', this.value)\" style=\"width:100%; accent-color:var(--ank-cyan);\">\r\n                <\/div>\r\n            <\/div>\r\n\r\n            <!-- CAT 4: SELECTION & WATERMARK -->\r\n            <div class=\"ank-tool-category\">\r\n                <div class=\"ank-cat-title\">4. Scope & Watermark<\/div>\r\n                <div style=\"display:flex; flex-direction:column; gap:3px;\">\r\n                    <div style=\"display:flex; gap:4px;\">\r\n                        <button type=\"button\" class=\"btn-main\" style=\"font-size:7px; height:24px; padding:0 4px; flex:1;\" onclick=\"toggleAllSelection(true)\">Select All<\/button>\r\n                        <button type=\"button\" class=\"btn-main\" style=\"font-size:7px; height:24px; padding:0 4px; flex:1; background:var(--ank-border);\" onclick=\"toggleAllSelection(false)\">Deselect All<\/button>\r\n                    <\/div>\r\n                    <input type=\"text\" id=\"suite-wm\" class=\"ank-control-input\" placeholder=\"Watermark Text...\">\r\n                <\/div>\r\n            <\/div>\r\n        <\/div>\r\n\r\n        <!-- WORKSPACE VIEWPORT -->\r\n        <div class=\"ank-workspace\">\r\n            <div class=\"ank-main-viewport\">\r\n                <span id=\"suite-placeholder\" style=\"color:var(--ank-border); font-weight:900; font-size:11px;\">UPLOAD IMAGE(S) TO START SUITE<\/span>\r\n                <img id=\"suite-active-img\" style=\"display:none;\">\r\n            <\/div>\r\n            <div class=\"ank-side-panel\">\r\n                <div>\r\n                    <div class=\"ank-cat-title\" style=\"margin-bottom:4px;\">Telemetry & Format<\/div>\r\n                    <div class=\"ank-info-box\" id=\"suite-telemetry\">\r\n                        Status: Ready for files...<br>\r\n                        Dimensions: N\/A<br>\r\n                        Size: N\/A\r\n                    <\/div>\r\n                <\/div>\r\n                <div style=\"display:flex; flex-direction:column; gap:4px;\">\r\n                    <div class=\"ank-cat-title\">Export Settings<\/div>\r\n                    <select id=\"suite-format\" class=\"ank-control-input\">\r\n                        <option value=\"jpeg\">JPG Image Format<\/option>\r\n                        <option value=\"png\">PNG Format<\/option>\r\n                        <option value=\"webp\">WebP Format<\/option>\r\n                    <\/select>\r\n                <\/div>\r\n            <\/div>\r\n        <\/div>\r\n\r\n        <!-- THUMBNAILS STRIP WITH CHECKBOXES -->\r\n        <div class=\"ank-thumbs\" id=\"suite-thumb-strip\"><\/div>\r\n\r\n        <!-- FOOTER ACTIONS -->\r\n        <div class=\"ank-foot\">\r\n            <input type=\"file\" id=\"suite-file-input\" accept=\"image\/*\" multiple onchange=\"handleSuiteFiles(this)\" style=\"font-size:10px; font-weight:bold; width:180px; color:var(--ank-text);\">\r\n            <div style=\"display:flex; gap:8px;\">\r\n                <button onclick=\"location.reload()\" class=\"btn-main btn-reset\">Reset Suite<\/button>\r\n                <button onclick=\"executeSuiteExport()\" id=\"suite-exec-btn\" class=\"btn-main btn-success\">Process & Download Selected \/ ZIP<\/button>\r\n            <\/div>\r\n        <\/div>\r\n\r\n        <script>\r\n            let suiteFiles = [];\r\n            let activeSuiteIdx = 0;\r\n            let suiteCropper = null;\r\n            let sX = 1, sY = 1;\r\n            let imageStates = {}; \r\n            let historyStacks = {}; \r\n            let redoStacks = {}; \r\n            let selectedImages = {}; \r\n            let globalAspectTemplate = NaN;\r\n\r\n            function handleSuiteFiles(input) {\r\n                if (input.files && input.files.length > 0) {\r\n                    suiteFiles = Array.from(input.files);\r\n                    document.getElementById('sys-tag').innerText = \"\u25cf READY (\" + suiteFiles.length + \" FILES)\";\r\n                    document.getElementById('suite-exec-btn').style.display = \"block\";\r\n                    \r\n                    const strip = document.getElementById('suite-thumb-strip');\r\n                    strip.innerHTML = \"\"; strip.style.display = \"flex\";\r\n\r\n                    suiteFiles.forEach((file, idx) => {\r\n                        imageStates[idx] = { brightness: 100, aspect: NaN, rotation: 0, customData: null };\r\n                        historyStacks[idx] = [];\r\n                        redoStacks[idx] = [];\r\n                        selectedImages[idx] = true;\r\n\r\n                        const reader = new FileReader();\r\n                        reader.readAsDataURL(file);\r\n                        reader.onload = e => {\r\n                            const card = document.createElement('div'); card.className = \"t-card\";\r\n                            card.innerHTML = `\r\n                                <div class=\"t-box ${idx === 0 ? 'active' : ''}\" onclick=\"switchSuiteImage(${idx})\" id=\"st-${idx}\"><img decoding=\"async\" src=\"${e.target.result}\"><\/div>\r\n                                <label class=\"t-check\"><input type=\"checkbox\" id=\"chk-${idx}\" checked onchange=\"selectedImages[${idx}] = this.checked\"> #${idx+1}<\/label>\r\n                            `;\r\n                            strip.appendChild(card);\r\n                            if (idx === 0) switchSuiteImage(0);\r\n                        };\r\n                    });\r\n                }\r\n            }\r\n\r\n            function toggleAllSelection(status) {\r\n                suiteFiles.forEach((_, idx) => {\r\n                    selectedImages[idx] = status;\r\n                    const chk = document.getElementById(`chk-${idx}`);\r\n                    if(chk) chk.checked = status;\r\n                });\r\n            }\r\n\r\n            function saveCurrentCropperState() {\r\n                if (suiteCropper) {\r\n                    imageStates[activeSuiteIdx].customData = suiteCropper.getData(true);\r\n                    imageStates[activeSuiteIdx].aspect = suiteCropper.options.aspectRatio;\r\n                }\r\n            }\r\n\r\n            function switchSuiteImage(idx) {\r\n                saveCurrentCropperState();\r\n\r\n                activeSuiteIdx = idx;\r\n                const file = suiteFiles[idx];\r\n                const reader = new FileReader();\r\n                reader.readAsDataURL(file);\r\n                reader.onload = e => {\r\n                    const img = document.getElementById('suite-active-img');\r\n                    img.src = e.target.result;\r\n                    img.style.display = \"block\";\r\n                    document.getElementById('suite-placeholder').style.display = \"none\";\r\n\r\n                    const bVal = imageStates[idx].brightness || 100;\r\n                    document.getElementById('sl-b').value = bVal;\r\n                    document.getElementById('inp-b').value = bVal;\r\n                    img.style.filter = `brightness(${bVal}%)`;\r\n\r\n                    const temp = new Image();\r\n                    temp.src = e.target.result;\r\n                    temp.onload = () => {\r\n                        document.getElementById('suite-telemetry').innerHTML = `\r\n                            File: ${file.name}<br>\r\n                            Orig Dim: <strong>${temp.width} x ${temp.height} px<\/strong><br>\r\n                            Size: <strong>${Math.round(file.size \/ 1024)} KB<\/strong>\r\n                        `;\r\n                    };\r\n\r\n                    if (suiteCropper) suiteCropper.destroy();\r\n\r\n                    let activeAspect = !isNaN(imageStates[idx].aspect) ? imageStates[idx].aspect : globalAspectTemplate;\r\n\r\n                    suiteCropper = new Cropper(img, {\r\n                        aspectRatio: activeAspect,\r\n                        viewMode: 1,\r\n                        autoCropArea: 1,\r\n                        responsive: true,\r\n                        ready() {\r\n                            if (imageStates[idx].customData) {\r\n                                suiteCropper.setData(imageStates[idx].customData);\r\n                            }\r\n                        },\r\n                        cropend() {\r\n                            saveCurrentCropperState();\r\n                            historyStacks[activeSuiteIdx].push(suiteCropper.getData());\r\n                            redoStacks[activeSuiteIdx] = [];\r\n                        }\r\n                    });\r\n\r\n                    document.querySelectorAll('.t-box').forEach((b, i) => b.classList.toggle('active', i === idx));\r\n                };\r\n            }\r\n\r\n            function applyGlobalRatio(val) { \r\n                const asp = parseFloat(val);\r\n                globalAspectTemplate = asp;\r\n\r\n                suiteFiles.forEach((_, i) => {\r\n                    if(selectedImages[i]) {\r\n                        imageStates[i].aspect = asp;\r\n                        imageStates[i].customData = null;\r\n                    }\r\n                });\r\n\r\n                if(suiteCropper) { \r\n                    suiteCropper.setAspectRatio(asp);\r\n                    suiteCropper.setCropBoxData(suiteCropper.getContainerData());\r\n                    saveCurrentCropperState();\r\n                }\r\n            }\r\n\r\n            function suiteRotate(deg) { \r\n                if(suiteCropper) { suiteCropper.rotate(deg); saveCurrentCropperState(); } \r\n            }\r\n\r\n            function suiteFineRotate(deg) { \r\n                if(suiteCropper) { suiteCropper.rotateTo(parseFloat(deg)); saveCurrentCropperState(); } \r\n            }\r\n\r\n            function suiteFlipX() { \r\n                if(suiteCropper) { sX *= -1; suiteCropper.scaleX(sX); saveCurrentCropperState(); } \r\n            }\r\n\r\n            function suiteFlipY() { \r\n                if(suiteCropper) { sY *= -1; suiteCropper.scaleY(sY); saveCurrentCropperState(); } \r\n            }\r\n\r\n            function suiteReset() { \r\n                if(suiteCropper) { \r\n                    suiteCropper.reset(); \r\n                    imageStates[activeSuiteIdx].brightness = 100;\r\n                    imageStates[activeSuiteIdx].aspect = NaN;\r\n                    imageStates[activeSuiteIdx].customData = null;\r\n                    document.getElementById('sl-b').value = 100;\r\n                    document.getElementById('inp-b').value = 100;\r\n                    document.getElementById('suite-ratio-list').value = \"NaN\";\r\n                    document.getElementById('suite-active-img').style.filter = 'brightness(100%)';\r\n                } \r\n            }\r\n\r\n            function suiteUndo() {\r\n                const stack = historyStacks[activeSuiteIdx];\r\n                if (stack && stack.length > 0) {\r\n                    const current = suiteCropper.getData();\r\n                    redoStacks[activeSuiteIdx].push(current);\r\n                    const prev = stack.pop();\r\n                    suiteCropper.setData(prev);\r\n                }\r\n            }\r\n\r\n            function suiteRedo() {\r\n                const rStack = redoStacks[activeSuiteIdx];\r\n                if (rStack && rStack.length > 0) {\r\n                    const current = suiteCropper.getData();\r\n                    historyStacks[activeSuiteIdx].push(current);\r\n                    const next = rStack.pop();\r\n                    suiteCropper.setData(next);\r\n                }\r\n            }\r\n\r\n            function syncSuiteSlider(type, val) {\r\n                document.getElementById('inp-' + type).value = val;\r\n                imageStates[activeSuiteIdx].brightness = val;\r\n                applySuiteFilters();\r\n            }\r\n            function syncSuiteVal(type, val) {\r\n                document.getElementById('sl-' + type).value = val;\r\n                imageStates[activeSuiteIdx].brightness = val;\r\n                applySuiteFilters();\r\n            }\r\n            function applySuiteFilters() {\r\n                const b = document.getElementById('sl-b').value;\r\n                const img = document.getElementById('suite-active-img');\r\n                if(img) img.style.filter = `brightness(${b}%)`;\r\n            }\r\n\r\n            async function executeSuiteExport() {\r\n                if (suiteFiles.length === 0) return alert(\"Please upload files first!\");\r\n                saveCurrentCropperState();\r\n\r\n                const format = document.getElementById('suite-format').value;\r\n                const wmText = document.getElementById('suite-wm').value.trim();\r\n                const activeIndices = Object.keys(selectedImages).filter(idx => selectedImages[idx]);\r\n\r\n                if (activeIndices.length === 0) return alert(\"Please select at least one image to process!\");\r\n\r\n                if (activeIndices.length === 1 && suiteFiles.length === 1) {\r\n                    if(!suiteCropper) return alert(\"Please select an image!\");\r\n                    const canvas = suiteCropper.getCroppedCanvas();\r\n                    const b = imageStates[activeSuiteIdx].brightness || 100;\r\n                    processCanvasExport(canvas, format, wmText, b, `AnkMaven-Edited.${format}`);\r\n                } else {\r\n                    const zip = new JSZip();\r\n\r\n                    for (let k = 0; k < activeIndices.length; k++) {\r\n                        const i = activeIndices[k];\r\n                        const file = suiteFiles[i];\r\n                        const state = imageStates[i];\r\n\r\n                        const blobData = await processTargetImageBlob(file, format, wmText, state);\r\n                        zip.file(`AnkMaven-Selected-${parseInt(i)+1}.${format}`, blobData);\r\n                    }\r\n                    const content = await zip.generateAsync({type: \"blob\"});\r\n                    const a = document.createElement('a');\r\n                    a.href = URL.createObjectURL(content);\r\n                    a.download = \"AnkMaven_Selected_Processed.zip\";\r\n                    a.click();\r\n                }\r\n            }\r\n\r\n            function processCanvasExport(canvas, format, wmText, brightness, filename) {\r\n                const finalC = document.createElement('canvas');\r\n                finalC.width = canvas.width; finalC.height = canvas.height;\r\n                const ctx = finalC.getContext('2d');\r\n                ctx.filter = `brightness(${brightness}%)`;\r\n                ctx.drawImage(canvas, 0, 0);\r\n                ctx.filter = 'none';\r\n\r\n                if(wmText) {\r\n                    ctx.font = `bold ${Math.max(14, Math.round(finalC.width\/30))}px Inter, sans-serif`;\r\n                    ctx.fillStyle = \"rgba(255,255,255,0.9)\";\r\n                    ctx.strokeStyle = \"rgba(0,0,0,0.7)\"; ctx.lineWidth = 2;\r\n                    ctx.strokeText(wmText, finalC.width - 150, finalC.height - 20);\r\n                    ctx.fillText(wmText, finalC.width - 150, finalC.height - 20);\r\n                }\r\n\r\n                finalC.toBlob(blob => {\r\n                    const a = document.createElement('a');\r\n                    a.href = URL.createObjectURL(blob);\r\n                    a.download = filename;\r\n                    a.click();\r\n                }, `image\/${format}`, 0.9);\r\n            }\r\n\r\n            function processTargetImageBlob(file, format, wmText, state) {\r\n                return new Promise(resolve => {\r\n                    const reader = new FileReader();\r\n                    reader.readAsDataURL(file);\r\n                    reader.onload = e => {\r\n                        const img = new Image();\r\n                        img.src = e.target.result;\r\n                        img.onload = () => {\r\n                            let sx = 0, sy = 0, sWidth = img.width, sHeight = img.height;\r\n\r\n                            if (state.customData) {\r\n                                sx = Math.max(0, state.customData.x);\r\n                                sy = Math.max(0, state.customData.y);\r\n                                sWidth = Math.min(img.width - sx, state.customData.width);\r\n                                sHeight = Math.min(img.height - sy, state.customData.height);\r\n                            } else if (!isNaN(state.aspect) && state.aspect > 0) {\r\n                                const currentAspect = img.width \/ img.height;\r\n                                if (currentAspect > state.aspect) {\r\n                                    sHeight = img.height;\r\n                                    sWidth = Math.round(img.height * state.aspect);\r\n                                    sx = (img.width - sWidth) \/ 2;\r\n                                } else {\r\n                                    sWidth = img.width;\r\n                                    sHeight = Math.round(img.width \/ state.aspect);\r\n                                    sy = (img.height - sHeight) \/ 2;\r\n                                }\r\n                            }\r\n\r\n                            const c = document.createElement('canvas');\r\n                            c.width = sWidth; c.height = sHeight;\r\n                            const ctx = c.getContext('2d');\r\n                            ctx.filter = `brightness(${state.brightness}%)`;\r\n                            ctx.drawImage(img, sx, sy, sWidth, sHeight, 0, 0, sWidth, sHeight);\r\n\r\n                            if(wmText) {\r\n                                ctx.font = `bold ${Math.max(14, Math.round(sWidth\/30))}px Inter, sans-serif`;\r\n                                ctx.fillStyle = \"rgba(255,255,255,0.9)\";\r\n                                ctx.strokeStyle = \"rgba(0,0,0,0.7)\"; ctx.lineWidth = 2;\r\n                                ctx.strokeText(wmText, sWidth - 150, sHeight - 20);\r\n                                ctx.fillText(wmText, sWidth - 150, sHeight - 20);\r\n                            }\r\n\r\n                            c.toBlob(blob => resolve(blob || file), `image\/${format}`, 0.9);\r\n                        };\r\n                    };\r\n                });\r\n            }\r\n        <\/script>\r\n    <\/div>\r\n    <\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\n<\/div>\n\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-43","page","type-page","status-publish","hentry"],"_hostinger_reach_plugin_has_subscription_block":false,"_hostinger_reach_plugin_is_elementor":false,"_links":{"self":[{"href":"https:\/\/ankmavenmarketing.in\/tools\/wp-json\/wp\/v2\/pages\/43","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ankmavenmarketing.in\/tools\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/ankmavenmarketing.in\/tools\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/ankmavenmarketing.in\/tools\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/ankmavenmarketing.in\/tools\/wp-json\/wp\/v2\/comments?post=43"}],"version-history":[{"count":14,"href":"https:\/\/ankmavenmarketing.in\/tools\/wp-json\/wp\/v2\/pages\/43\/revisions"}],"predecessor-version":[{"id":85,"href":"https:\/\/ankmavenmarketing.in\/tools\/wp-json\/wp\/v2\/pages\/43\/revisions\/85"}],"wp:attachment":[{"href":"https:\/\/ankmavenmarketing.in\/tools\/wp-json\/wp\/v2\/media?parent=43"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}