From 51d52d3a0795d59986420db5e40e512d9508dd1c Mon Sep 17 00:00:00 2001 From: JeLuF Date: Fri, 2 Jun 2023 23:41:53 +0200 Subject: [PATCH 1/2] Tiled image download plugin --- ui/plugins/ui/tiled-image-download.plugin.js | 325 +++++++++++++++++++ 1 file changed, 325 insertions(+) create mode 100644 ui/plugins/ui/tiled-image-download.plugin.js diff --git a/ui/plugins/ui/tiled-image-download.plugin.js b/ui/plugins/ui/tiled-image-download.plugin.js new file mode 100644 index 00000000..aaceab46 --- /dev/null +++ b/ui/plugins/ui/tiled-image-download.plugin.js @@ -0,0 +1,325 @@ +;(function(){ + "use strict"; + const PAPERSIZE = [ + {id: "a3p", width: 297, height: 420, unit: "mm"}, + {id: "a3l", width: 420, height: 297, unit: "mm"}, + {id: "a4p", width: 210, height: 297, unit: "mm"}, + {id: "a4l", width: 297, height: 210, unit: "mm"}, + {id: "ll", width: 279, height: 216, unit: "mm"}, + {id: "lp", width: 216, height: 279, unit: "mm"}, + {id: "hd", width: 1920, height: 1080, unit: "pixels"}, + {id: "4k", width: 3840, height: 2160, unit: "pixels"}, + ] + + // ---- Register plugin + PLUGINS['IMAGE_INFO_BUTTONS'].push({ + html: ' Download tiled image', + on_click: onDownloadTiledImage, + filter: (req, img) => req.tiling != "none", + }) + + var thisImage + + function onDownloadTiledImage(req, img) { + document.getElementById("download-tiled-image-dialog").showModal() + thisImage = new Image() + thisImage.src = img.src + thisImage.dataset["prompt"] = img.dataset["prompt"] + } + + // ---- Add HTML + document.getElementById('container').lastElementChild.insertAdjacentHTML("afterend", + ` +

Download tiled image

+
+
+
+ + Number of tiles + + + Image dimensions + +
+
+
+
+ + +
+
+
+
+
+ + + +
+
+ +
+
+ Some standard sizes:
+
+
+
+ +
+
+
+
+
+
+
+ + Tile placement + +
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+ +
+
+ +
+
+ +
+
+
`) + + let downloadTiledImageDialog = document.getElementById("download-tiled-image-dialog") + let dtim1_width = document.getElementById("dtim1-width") + let dtim1_height = document.getElementById("dtim1-height") + let dtim2_width = document.getElementById("dtim2-width") + let dtim2_height = document.getElementById("dtim2-height") + let dtim2_unit = document.getElementById("dtim2-unit") + let dtim2_dpi = document.getElementById("dtim2-dpi") + let tabTiledTilesOptions = document.getElementById("tab-image-tiles") + let tabTiledSizeOptions = document.getElementById("tab-image-size") + + linkTabContents(tabTiledTilesOptions) + linkTabContents(tabTiledSizeOptions) + + prettifyInputs(downloadTiledImageDialog) + + // ---- Predefined image dimensions + PAPERSIZE.forEach( function(p) { + document.getElementById("dtim2-" + p.id).addEventListener("click", (e) => { + dtim2_unit.value = p.unit + dtim2_width.value = p.width + dtim2_height.value = p.height + }) + }) + + // ---- Close popup + document.getElementById("dti-cancel").addEventListener("click", (e) => downloadTiledImageDialog.close()) + downloadTiledImageDialog.addEventListener('click', function (event) { + var rect = downloadTiledImageDialog.getBoundingClientRect(); + var isInDialog=(rect.top <= event.clientY && event.clientY <= rect.top + rect.height + && rect.left <= event.clientX && event.clientX <= rect.left + rect.width); + if (!isInDialog) { + downloadTiledImageDialog.close(); + } + }); + + // ---- Stylesheet + const styleSheet = document.createElement("style") + styleSheet.textContent = ` + dialog { + background: var(--background-color2); + color: var(--text-color); + border-radius: 7px; + border: 1px solid var(--background-color3); + } + + dialog::backdrop { + background: rgba(0, 0, 0, 0.5); + } + + + button[disabled] { + opacity: 0.5; + } + + .method-2-dpi { + margin-top: 1em; + margin-bottom: 1em; + } + + .method-2-paper button { + width: 10em; + padding: 4px; + margin: 4px; + } + + .download-tiled-image .tab-content { + background: var(--background-color1); + border-radius: 3pt; + } + + .dtim-container { display: grid; + grid-template-columns: auto auto; + grid-template-rows: auto auto; + gap: 1em 0px; + grid-auto-flow: row; + grid-template-areas: + "dtim-tab dtim-tab dtim-plc" + "dtim-ok dtim-newtab dtim-cancel"; + } + + .download-tiled-image-top { + justify-self: center; + grid-area: dtim-tab; + } + + .download-tiled-image-placement { + justify-self: center; + grid-area: dtim-plc; + margin-left: 1em; + } + + .dtim-ok { + justify-self: center; + align-self: start; + grid-area: dtim-ok; + } + + .dtim-newtab { + justify-self: center; + align-self: start; + grid-area: dtim-newtab; + } + + .dtim-cancel { + justify-self: center; + align-self: start; + grid-area: dtim-cancel; + } + + #tab-content-image-placement img { + margin: 4px; + opacity: 0.3; + border: solid 2px var(--background-color1); + } + + #tab-content-image-placement img:hover { + margin: 4px; + opacity: 1; + border: solid 2px var(--accent-color); + filter: brightness(2); + } + + #tab-content-image-placement img.active { + margin: 4px; + opacity: 1; + border: solid 2px var(--background-color1); + } + + ` + document.head.appendChild(styleSheet) + + // ---- Placement widget + + function updatePlacementWidget(event) { + document.querySelector("#tab-content-image-placement img.active").classList.remove("active") + event.target.classList.add("active") + } + + document.querySelectorAll("#tab-content-image-placement img").forEach( + (i) => i.addEventListener("click", updatePlacementWidget) + ) + + function getPlacement() { + return document.querySelector("#tab-content-image-placement img.active").id.substr(5) + } + + // ---- Make the image + function downloadTiledImage(image, width, height, offsetX=0, offsetY=0, new_tab=false) { + + const canvas = document.createElement('canvas') + canvas.width = width + canvas.height = height + const context = canvas.getContext('2d') + + const w = image.width + const h = image.height + + for (var x = offsetX; x < width; x += w) { + for (var y = offsetY; y < height; y += h) { + context.drawImage(image, x, y, w, h) + } + } + if (new_tab) { + var newTab = window.open("") + newTab.document.write(`${width}×${height}, "${image.dataset["prompt"]}"`) + } else { + const link = document.createElement('a') + link.href = canvas.toDataURL() + link.download = image.dataset["prompt"].replace(/[^a-zA-Z0-9]+/g, "-").substr(0,22)+crypto.randomUUID()+".png" + link.click() + } + } + + function onDownloadTiledImageClick(e, newtab=false) { + var width, height, offsetX, offsetY + + if (isTabActive(tabTiledTilesOptions)) { + width = thisImage.width * dtim1_width.value + height = thisImage.height * dtim1_height.value + } else { + if ( dtim2_unit.value == "pixels" ) { + width = dtim2_width.value + height= dtim2_height.value + } else if ( dtim2_unit.value == "mm" ) { + width = Math.floor( dtim2_width.value * dtim2_dpi.value / 25.4 ) + height = Math.floor( dtim2_height.value * dtim2_dpi.value / 25.4 ) + } else { // inch + width = Math.floor( dtim2_width.value * dtim2_dpi.value ) + height = Math.floor( dtim2_height.value * dtim2_dpi.value ) + } + } + + var placement = getPlacement() + if (placement == "1tl") { + offsetX = 0 + offsetY = 0 + } else if (placement == "1tr") { + offsetX = width - thisImage.width * Math.ceil( width / thisImage.width ) + offsetY = 0 + } else if (placement == "1bl") { + offsetX = 0 + offsetY = height - thisImage.height * Math.ceil( height / thisImage.height ) + } else if (placement == "1br") { + offsetX = width - thisImage.width * Math.ceil( width / thisImage.width ) + offsetY = height - thisImage.height * Math.ceil( height / thisImage.height ) + } else if (placement == "4center") { + offsetX = width/2 - thisImage.width * Math.ceil( width/2 / thisImage.width ) + offsetY = height/2 - thisImage.height * Math.ceil( height/2 / thisImage.height ) + } else if (placement == "1center") { + offsetX = width/2 - thisImage.width/2 - thisImage.width * Math.ceil( (width/2 - thisImage.width/2) / thisImage.width ) + offsetY = height/2 - thisImage.height/2 - thisImage.height * Math.ceil( (height/2 - thisImage.height/2) / thisImage.height ) + } + downloadTiledImage(thisImage, width, height, offsetX, offsetY, newtab) + } + + document.getElementById("dti-ok").addEventListener("click", onDownloadTiledImageClick) + document.getElementById("dti-newtab").addEventListener("click", (e) => onDownloadTiledImageClick(e,true)) + +})() From 6dcf7539bb9b92bc70c0d3af85bd4fc7282e30bb Mon Sep 17 00:00:00 2001 From: JeLuF Date: Sat, 3 Jun 2023 00:04:13 +0200 Subject: [PATCH 2/2] close window --- ui/plugins/ui/tiled-image-download.plugin.js | 1 + 1 file changed, 1 insertion(+) diff --git a/ui/plugins/ui/tiled-image-download.plugin.js b/ui/plugins/ui/tiled-image-download.plugin.js index aaceab46..0fe00c2e 100644 --- a/ui/plugins/ui/tiled-image-download.plugin.js +++ b/ui/plugins/ui/tiled-image-download.plugin.js @@ -317,6 +317,7 @@ offsetY = height/2 - thisImage.height/2 - thisImage.height * Math.ceil( (height/2 - thisImage.height/2) / thisImage.height ) } downloadTiledImage(thisImage, width, height, offsetX, offsetY, newtab) + downloadTiledImageDialog.close() } document.getElementById("dti-ok").addEventListener("click", onDownloadTiledImageClick)