{"id":699,"date":"2025-03-11T13:43:37","date_gmt":"2025-03-11T13:43:37","guid":{"rendered":"https:\/\/divbydev.com\/?page_id=699"},"modified":"2025-03-12T21:50:48","modified_gmt":"2025-03-12T21:50:48","slug":"watermark-maker","status":"publish","type":"page","link":"https:\/\/divbydev.com\/index.php\/projects-2\/watermark-maker\/","title":{"rendered":"Watermark Maker"},"content":{"rendered":"\n<p>Stuff<\/p>\n\n\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\">\n  <title>Visible Watermark Embedder<\/title>\n  <style>\n    body {\n      font-family: Arial, sans-serif;\n      margin: 20px;\n    }\n    \n    #controls {\n      margin-bottom: 20px;\n      max-width: 400px;\n    }\n    \n    canvas {\n      border: 1px solid #ccc;\n      margin-top: 10px;\n      max-width: 100%;\n      height: auto;\n    }\n    \n    input[type=\"file\"],\n    input[type=\"text\"],\n    input[type=\"number\"],\n    input[type=\"range\"],\n    select {\n      display: block;\n      margin-bottom: 10px;\n      width: 100%;\n      max-width: 400px;\n    }\n    \n    label {\n      display: block;\n      margin-bottom: 10px;\n    }\n    \n    button {\n      margin-right: 10px;\n    }\n    \n    span {\n      margin-left: 10px;\n      font-weight: bold;\n    }\n  <\/style>\n<\/head>\n<body>\n  <div id=\"controls\">\n    <!-- File selector -->\n    <input type=\"file\" id=\"fileInput\" accept=\"image\/*\">\n\n    <!-- Watermark text input -->\n    <input type=\"text\" id=\"watermarkText\" placeholder=\"Enter watermark text\" value=\"\u00a9 MyBrand\">\n\n    <!-- Watermark opacity input -->\n    <label>\n      Watermark Opacity (%):\n      <input type=\"number\" id=\"watermarkOpacity\" value=\"50\" min=\"0\" max=\"100\">\n      <span id=\"watermarkOpacityVal\">50%<\/span>\n    <\/label>\n\n    <!-- Watermark X position slider -->\n    <label>\n      Watermark X Position (%):\n      <input type=\"range\" id=\"watermarkX\" min=\"0\" max=\"100\" value=\"50\">\n      <span id=\"watermarkXVal\">50%<\/span>\n    <\/label>\n\n    <!-- Watermark Y position slider -->\n    <label>\n      Watermark Y Position (%):\n      <input type=\"range\" id=\"watermarkY\" min=\"0\" max=\"100\" value=\"50\">\n      <span id=\"watermarkYVal\">50%<\/span>\n    <\/label>\n\n    <!-- Extended Watermark Alignment drop-down -->\n    <label>\n      Watermark Alignment:\n      <select id=\"watermarkAlign\">\n        <option value=\"custom\">Custom<\/option>\n        <option value=\"top left\">Top Left<\/option>\n        <option value=\"top centre\">Top Centre<\/option>\n        <option value=\"top right\">Top Right<\/option>\n        <option value=\"centre left\">Centre Left<\/option>\n        <option value=\"centre\">Centre<\/option>\n        <option value=\"centre right\">Centre Right<\/option>\n        <option value=\"bottom left\">Bottom Left<\/option>\n        <option value=\"bottom centre\">Bottom Centre<\/option>\n        <option value=\"bottom right\">Bottom Right<\/option>\n      <\/select>\n    <\/label>\n\n    <!-- Watermark Font Size numerical input -->\n    <label>\n      Watermark Font Size (% of image height):\n      <input type=\"number\" id=\"watermarkFontSize\" value=\"5\" min=\"1\" max=\"20\">%\n      <span id=\"watermarkFontSizeVal\">5%<\/span>\n    <\/label>\n\n    <!-- Watermark Font Style drop-down (10 choices) -->\n    <label>\n      Font Style:\n      <select id=\"watermarkFontStyle\">\n        <option value=\"Arial\">Arial<\/option>\n        <option value=\"Helvetica\">Helvetica<\/option>\n        <option value=\"Verdana\">Verdana<\/option>\n        <option value=\"Tahoma\">Tahoma<\/option>\n        <option value=\"Trebuchet MS\">Trebuchet MS<\/option>\n        <option value=\"Georgia\">Georgia<\/option>\n        <option value=\"Times New Roman\">Times New Roman<\/option>\n        <option value=\"Courier New\">Courier New<\/option>\n        <option value=\"Lucida Sans\">Lucida Sans<\/option>\n        <option value=\"Segoe UI\">Segoe UI<\/option>\n      <\/select>\n    <\/label>\n\n    <!-- Watermark Colour picker -->\n    <label>\n      Text Colour:\n      <input type=\"color\" id=\"watermarkColor\" value=\"#000000\">\n    <\/label>\n\n    <!-- Text Direction drop-down (for the watermark text) -->\n    <label>\n      Text Direction:\n      <select id=\"textDirection\">\n        <option value=\"horizontal\" selected>Horizontal<\/option>\n        <option value=\"vertical\">Vertical<\/option>\n        <option value=\"diagonalTLBR\">Diagonal TL\u2013BR<\/option>\n        <option value=\"diagonalBLTR\">Diagonal BL\u2013TR<\/option>\n      <\/select>\n    <\/label>\n\n    <button id=\"saveBtn\">Save Watermarked Image<\/button>\n    <button id=\"clearBtn\">Clear<\/button>\n  <\/div>\n  \n  <canvas id=\"canvas\"><\/canvas>\n  \n  <script>\n    const fileInput = document.getElementById('fileInput');\n    const watermarkTextInput = document.getElementById('watermarkText');\n    const watermarkOpacityInput = document.getElementById('watermarkOpacity');\n    const watermarkXInput = document.getElementById('watermarkX');\n    const watermarkYInput = document.getElementById('watermarkY');\n    const watermarkOpacityVal = document.getElementById('watermarkOpacityVal');\n    const watermarkXVal = document.getElementById('watermarkXVal');\n    const watermarkYVal = document.getElementById('watermarkYVal');\n    const watermarkAlignSelect = document.getElementById('watermarkAlign');\n    const watermarkFontSizeInput = document.getElementById('watermarkFontSize');\n    const watermarkFontSizeVal = document.getElementById('watermarkFontSizeVal');\n    const watermarkFontStyleSelect = document.getElementById('watermarkFontStyle');\n    const watermarkColorInput = document.getElementById('watermarkColor');\n    const textDirectionSelect = document.getElementById('textDirection');\n\n    const saveBtn = document.getElementById('saveBtn');\n    const clearBtn = document.getElementById('clearBtn');\n    const canvas = document.getElementById('canvas');\n    const ctx = canvas.getContext('2d');\n    let originalImage = null;\n\n    \/\/ Helper function to get alignment values for watermark text\n    function getAlignmentValues(alignment) {\n      let align, baseline;\n      switch (alignment) {\n        case \"top left\":\n          align = \"left\"; baseline = \"top\"; break;\n        case \"top centre\":\n          align = \"center\"; baseline = \"top\"; break;\n        case \"top right\":\n          align = \"right\"; baseline = \"top\"; break;\n        case \"centre left\":\n          align = \"left\"; baseline = \"middle\"; break;\n        case \"centre\":\n          align = \"center\"; baseline = \"middle\"; break;\n        case \"centre right\":\n          align = \"right\"; baseline = \"middle\"; break;\n        case \"bottom left\":\n          align = \"left\"; baseline = \"bottom\"; break;\n        case \"bottom centre\":\n          align = \"center\"; baseline = \"bottom\"; break;\n        case \"bottom right\":\n          align = \"right\"; baseline = \"bottom\"; break;\n        default:\n          align = \"center\"; baseline = \"middle\";\n      }\n      return { align, baseline };\n    }\n\n    \/\/ Update all indicator values.\n    function updateIndicators() {\n      watermarkOpacityVal.innerText = watermarkOpacityInput.value + '%';\n      watermarkXVal.innerText = watermarkXInput.value + '%';\n      watermarkYVal.innerText = watermarkYInput.value + '%';\n      watermarkFontSizeVal.innerText = watermarkFontSizeInput.value + '%';\n    }\n\n    \/\/ Event listeners\n    watermarkOpacityInput.addEventListener('input', () => { updateIndicators(); updateCanvas(); });\n    watermarkXInput.addEventListener('input', () => { updateIndicators(); updateCanvas(); });\n    watermarkYInput.addEventListener('input', () => { updateIndicators(); updateCanvas(); });\n    watermarkFontSizeInput.addEventListener('input', () => { updateIndicators(); updateCanvas(); });\n    watermarkTextInput.addEventListener('input', updateCanvas);\n    watermarkFontStyleSelect.addEventListener('change', updateCanvas);\n    watermarkColorInput.addEventListener('input', updateCanvas);\n    textDirectionSelect.addEventListener('change', updateCanvas);\n\n    \/\/ Update watermark alignment preset: if not custom, update X\/Y sliders.\n    function updateWatermarkAlignmentPreset() {\n      if (!originalImage) return;\n      const preset = watermarkAlignSelect.value;\n      let xPos, yPos;\n      const width = originalImage.width;\n      const height = originalImage.height;\n      \n      if (preset !== \"custom\") {\n        switch (preset) {\n          case \"top left\":\n            xPos = 0; yPos = 0; break;\n          case \"top centre\":\n            xPos = width \/ 2; yPos = 0; break;\n          case \"top right\":\n            xPos = width; yPos = 0; break;\n          case \"centre left\":\n            xPos = 0; yPos = height \/ 2; break;\n          case \"centre\":\n            xPos = width \/ 2; yPos = height \/ 2; break;\n          case \"centre right\":\n            xPos = width; yPos = height \/ 2; break;\n          case \"bottom left\":\n            xPos = 0; yPos = height; break;\n          case \"bottom centre\":\n            xPos = width \/ 2; yPos = height; break;\n          case \"bottom right\":\n            xPos = width; yPos = height; break;\n          default:\n            xPos = width * (parseFloat(watermarkXInput.value) \/ 100);\n            yPos = height * (parseFloat(watermarkYInput.value) \/ 100);\n        }\n        watermarkXInput.value = Math.round((xPos \/ width) * 100);\n        watermarkYInput.value = Math.round((yPos \/ height) * 100);\n        updateIndicators();\n        updateCanvas();\n      }\n    }\n    watermarkAlignSelect.addEventListener('change', updateWatermarkAlignmentPreset);\n\n    \/\/ Load image.\n    fileInput.addEventListener('change', () => {\n      if (fileInput.files && fileInput.files[0]) {\n        const reader = new FileReader();\n        reader.onload = function(event) {\n          originalImage = new Image();\n          originalImage.onload = () => {\n            canvas.width = originalImage.width;\n            canvas.height = originalImage.height;\n            updateCanvas();\n          };\n          originalImage.src = event.target.result;\n        };\n        reader.readAsDataURL(fileInput.files[0]);\n      }\n    });\n\n    \/\/ Update canvas with watermark overlay\n    function updateCanvas() {\n      if (!originalImage) return;\n      const width = originalImage.width;\n      const height = originalImage.height;\n      canvas.width = width;\n      canvas.height = height;\n      \n      \/\/ Draw the base image.\n      ctx.clearRect(0, 0, width, height);\n      ctx.drawImage(originalImage, 0, 0, width, height);\n      \n      \/\/ Draw watermark text.\n      ctx.save();\n      ctx.globalAlpha = parseFloat(watermarkOpacityInput.value) \/ 100;\n      \n      \/\/ Compute watermark font size (percentage of image height).\n      const watermarkFontSize = Math.floor(height * (parseFloat(watermarkFontSizeInput.value) \/ 100));\n      const fontStyle = watermarkFontStyleSelect.value;\n      ctx.font = `bold ${watermarkFontSize}px ${fontStyle}`;\n      ctx.fillStyle = watermarkColorInput.value;\n      \n      \/\/ Determine watermark position.\n      let xPos, yPos;\n      if (watermarkAlignSelect.value !== \"custom\") {\n        switch (watermarkAlignSelect.value) {\n          case \"top left\":\n            xPos = 0; yPos = 0; break;\n          case \"top centre\":\n            xPos = width \/ 2; yPos = 0; break;\n          case \"top right\":\n            xPos = width; yPos = 0; break;\n          case \"centre left\":\n            xPos = 0; yPos = height \/ 2; break;\n          case \"centre\":\n            xPos = width \/ 2; yPos = height \/ 2; break;\n          case \"centre right\":\n            xPos = width; yPos = height \/ 2; break;\n          case \"bottom left\":\n            xPos = 0; yPos = height; break;\n          case \"bottom centre\":\n            xPos = width \/ 2; yPos = height; break;\n          case \"bottom right\":\n            xPos = width; yPos = height; break;\n          default:\n            xPos = width * (parseFloat(watermarkXInput.value) \/ 100);\n            yPos = height * (parseFloat(watermarkYInput.value) \/ 100);\n        }\n      } else {\n        xPos = width * (parseFloat(watermarkXInput.value) \/ 100);\n        yPos = height * (parseFloat(watermarkYInput.value) \/ 100);\n      }\n      \n      \/\/ Align the text according to the preset.\n      const alignment = getAlignmentValues(watermarkAlignSelect.value);\n      ctx.textAlign = alignment.align;\n      ctx.textBaseline = alignment.baseline;\n      \n      \/\/ Apply direction (rotate if vertical or diagonal).\n      const direction = textDirectionSelect.value;\n      ctx.save();\n      if (direction === \"vertical\") {\n        ctx.translate(xPos, yPos);\n        ctx.rotate(-Math.PI \/ 2);\n        ctx.translate(-xPos, -yPos);\n      } else if (direction === \"diagonalTLBR\") {\n        ctx.translate(xPos, yPos);\n        ctx.rotate(Math.PI \/ 4);\n        ctx.translate(-xPos, -yPos);\n      } else if (direction === \"diagonalBLTR\") {\n        ctx.translate(xPos, yPos);\n        ctx.rotate(-Math.PI \/ 4);\n        ctx.translate(-xPos, -yPos);\n      }\n      \n      ctx.fillText(watermarkTextInput.value || \"\u00a9 MyBrand\", xPos, yPos);\n      ctx.restore();\n      ctx.restore();\n    }\n\n    \/\/ Save button\n    saveBtn.addEventListener('click', () => {\n      if (!originalImage || canvas.width === 0 || canvas.height === 0) {\n        alert(\"Please load an image first.\");\n        return;\n      }\n      const link = document.createElement('a');\n      link.download = 'watermarked_image.png';\n      link.href = canvas.toDataURL('image\/png');\n      link.click();\n    });\n\n    \/\/ Clear button\n    clearBtn.addEventListener('click', () => {\n      fileInput.value = '';\n      watermarkTextInput.value = '';\n      watermarkOpacityInput.value = 50;\n      watermarkXInput.value = 50;\n      watermarkYInput.value = 50;\n      watermarkAlignSelect.value = \"custom\";\n      watermarkFontSizeInput.value = 5;\n      watermarkFontStyleSelect.selectedIndex = 0;\n      watermarkColorInput.value = \"#000000\";\n      textDirectionSelect.value = \"horizontal\";\n      \n      updateIndicators();\n      ctx.clearRect(0, 0, canvas.width, canvas.height);\n      canvas.width = canvas.height = 0;\n      originalImage = null;\n    });\n  <\/script>\n<\/body>\n<\/html>\n","protected":false},"excerpt":{"rendered":"<p>Stuff Visible Watermark Embedder Watermark Opacity (%): 50% Watermark X Position (%): 50% Watermark Y Position (%): 50% Watermark Alignment: CustomTop LeftTop CentreTop RightCentre LeftCentreCentre RightBottom LeftBottom CentreBottom Right Watermark Font Size (% of image height): % 5% Font Style: ArialHelveticaVerdanaTahomaTrebuchet MSGeorgiaTimes New RomanCourier NewLucida SansSegoe UI Text Colour: Text Direction: HorizontalVerticalDiagonal TL\u2013BRDiagonal BL\u2013TR Save &#8230; <a title=\"Watermark Maker\" class=\"read-more\" href=\"https:\/\/divbydev.com\/index.php\/projects-2\/watermark-maker\/\" aria-label=\"Read more about Watermark Maker\">Read more<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"parent":230,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-699","page","type-page","status-publish"],"_links":{"self":[{"href":"https:\/\/divbydev.com\/index.php\/wp-json\/wp\/v2\/pages\/699","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/divbydev.com\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/divbydev.com\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/divbydev.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/divbydev.com\/index.php\/wp-json\/wp\/v2\/comments?post=699"}],"version-history":[{"count":1,"href":"https:\/\/divbydev.com\/index.php\/wp-json\/wp\/v2\/pages\/699\/revisions"}],"predecessor-version":[{"id":700,"href":"https:\/\/divbydev.com\/index.php\/wp-json\/wp\/v2\/pages\/699\/revisions\/700"}],"up":[{"embeddable":true,"href":"https:\/\/divbydev.com\/index.php\/wp-json\/wp\/v2\/pages\/230"}],"wp:attachment":[{"href":"https:\/\/divbydev.com\/index.php\/wp-json\/wp\/v2\/media?parent=699"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}