{"id":675,"date":"2025-03-04T16:06:35","date_gmt":"2025-03-04T16:06:35","guid":{"rendered":"https:\/\/divbydev.com\/?page_id=675"},"modified":"2025-03-12T21:40:14","modified_gmt":"2025-03-12T21:40:14","slug":"pixel-colour-replacer","status":"publish","type":"page","link":"https:\/\/divbydev.com\/index.php\/projects-2\/pixel-colour-replacer\/","title":{"rendered":"Pixel Colour Replacer"},"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>Pixel Color Replacer<\/title>\n  <style>\n    body {\n      font-family: Arial, sans-serif;\n      margin: 20px;\n    }\n    .container {\n      max-width: 800px;\n      margin: 0 auto;\n    }\n    .controls {\n      margin-bottom: 20px;\n    }\n    .controls label {\n      display: inline-block;\n      margin-right: 10px;\n    }\n    canvas {\n      border: 1px solid #ccc;\n      max-width: 100%;\n    }\n  <\/style>\n<\/head>\n<body>\n  <div class=\"container\">\n    <h1>Pixel Color Replacer<\/h1>\n    <div class=\"controls\">\n      <label>\n        Upload Image:\n        <input type=\"file\" id=\"imageInput\" accept=\"image\/*\">\n      <\/label>\n      <br><br>\n      <label>\n        Original Color:\n        <input type=\"color\" id=\"originalColor\" value=\"#ff0000\">\n      <\/label>\n      <label>\n        New Color:\n        <input type=\"color\" id=\"newColor\" value=\"#00ff00\">\n        <input type=\"checkbox\" id=\"transparentToggle\"> Transparent\n      <\/label>\n      <label>\n        Tolerance:\n        <input type=\"range\" id=\"tolerance\" min=\"0\" max=\"100\" value=\"10\">\n        <span id=\"tolValue\">10<\/span>%\n      <\/label>\n      <br><br>\n      <button id=\"replaceBtn\">Replace Color<\/button>\n      <button id=\"undoBtn\">Undo<\/button>\n      <button id=\"clearBtn\">Clear<\/button>\n      <button id=\"saveBtn\">Save Image<\/button>\n    <\/div>\n    <canvas id=\"canvas\"><\/canvas>\n  <\/div>\n  <script>\n    const canvas = document.getElementById(\"canvas\");\n    const ctx = canvas.getContext(\"2d\");\n\n    \/\/ History stack for undo functionality\n    let historyStack = [];\n\n    \/\/ Defaults for resetting\n    const defaultOriginalColor = \"#ff0000\";\n    const defaultNewColor = \"#00ff00\";\n    const defaultTolerance = 10;\n\n    \/\/ Load image from file input and draw on canvas\n    document.getElementById(\"imageInput\").addEventListener(\"change\", function(e) {\n      const file = e.target.files[0];\n      if (!file) return;\n      const reader = new FileReader();\n      reader.onload = function(event) {\n        const img = new Image();\n        img.onload = function() {\n          canvas.width = img.width;\n          canvas.height = img.height;\n          \/\/ Clear history when a new image is loaded\n          historyStack = [];\n          ctx.drawImage(img, 0, 0);\n        }\n        img.src = event.target.result;\n      }\n      reader.readAsDataURL(file);\n    });\n\n    \/\/ Update tolerance display value\n    document.getElementById(\"tolerance\").addEventListener(\"input\", function() {\n      document.getElementById(\"tolValue\").textContent = this.value;\n    });\n\n    \/\/ Button click: replace color in the canvas image\n    document.getElementById(\"replaceBtn\").addEventListener(\"click\", function() {\n      replaceColor();\n    });\n\n    \/\/ Undo button click: revert to previous state\n    document.getElementById(\"undoBtn\").addEventListener(\"click\", function() {\n      if (historyStack.length > 0) {\n        const previousData = historyStack.pop();\n        ctx.putImageData(previousData, 0, 0);\n      } else {\n        alert(\"No more undo steps.\");\n      }\n    });\n\n    \/\/ Clear button click: clear file input, canvas, and reset controls\n    document.getElementById(\"clearBtn\").addEventListener(\"click\", function() {\n      \/\/ Clear file input\n      document.getElementById(\"imageInput\").value = \"\";\n      \/\/ Clear canvas\n      ctx.clearRect(0, 0, canvas.width, canvas.height);\n      canvas.width = canvas.height = 0;\n      \/\/ Reset controls to defaults\n      document.getElementById(\"originalColor\").value = defaultOriginalColor;\n      document.getElementById(\"newColor\").value = defaultNewColor;\n      document.getElementById(\"tolerance\").value = defaultTolerance;\n      document.getElementById(\"tolValue\").textContent = defaultTolerance;\n      document.getElementById(\"transparentToggle\").checked = false;\n      \/\/ Clear history stack\n      historyStack = [];\n    });\n\n    \/\/ Save button click: save canvas as image\n    document.getElementById(\"saveBtn\").addEventListener(\"click\", function() {\n      if (canvas.width === 0 || canvas.height === 0) {\n        alert(\"No image to save.\");\n        return;\n      }\n      const link = document.createElement(\"a\");\n      link.download = \"replaced-image.png\";\n      link.href = canvas.toDataURL(\"image\/png\");\n      link.click();\n    });\n\n    \/\/ Convert hex color to RGB object\n    function hexToRgb(hex) {\n      hex = hex.replace(\"#\", \"\");\n      const bigint = parseInt(hex, 16);\n      const r = (bigint >> 16) & 255;\n      const g = (bigint >> 8) & 255;\n      const b = bigint & 255;\n      return { r, g, b };\n    }\n\n    \/\/ Replace pixels within tolerance of originalColor with newColor or transparent\n    function replaceColor() {\n      if (!canvas.width || !canvas.height) {\n        alert(\"Please upload an image first.\");\n        return;\n      }\n      \n      \/\/ Save current state for undo\n      historyStack.push(ctx.getImageData(0, 0, canvas.width, canvas.height));\n      \n      const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);\n      const data = imageData.data;\n      \n      const originalColor = hexToRgb(document.getElementById(\"originalColor\").value);\n      const tolerance = document.getElementById(\"tolerance\").value;\n      \/\/ Convert tolerance percentage (0-100) to a 0-255 scale\n      const tol = tolerance * 2.55;\n      const tolSq = tol * tol;\n      \n      const useTransparent = document.getElementById(\"transparentToggle\").checked;\n      let newColor = null;\n      if (!useTransparent) {\n        newColor = hexToRgb(document.getElementById(\"newColor\").value);\n      }\n      \n      for (let i = 0; i < data.length; i += 4) {\n        const dr = data[i] - originalColor.r;\n        const dg = data[i + 1] - originalColor.g;\n        const db = data[i + 2] - originalColor.b;\n        if (dr * dr + dg * dg + db * db <= tolSq) {\n          if (useTransparent) {\n            \/\/ Set alpha to 0 (transparent)\n            data[i + 3] = 0;\n          } else {\n            data[i] = newColor.r;\n            data[i + 1] = newColor.g;\n            data[i + 2] = newColor.b;\n          }\n        }\n      }\n      \n      ctx.putImageData(imageData, 0, 0);\n    }\n  <\/script>\n<\/body>\n<\/html>\n","protected":false},"excerpt":{"rendered":"<p>Stuff Pixel Color Replacer Pixel Color Replacer Upload Image: Original Color: New Color: Transparent Tolerance: 10% Replace Color Undo Clear Save Image<\/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-675","page","type-page","status-publish"],"_links":{"self":[{"href":"https:\/\/divbydev.com\/index.php\/wp-json\/wp\/v2\/pages\/675","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=675"}],"version-history":[{"count":1,"href":"https:\/\/divbydev.com\/index.php\/wp-json\/wp\/v2\/pages\/675\/revisions"}],"predecessor-version":[{"id":676,"href":"https:\/\/divbydev.com\/index.php\/wp-json\/wp\/v2\/pages\/675\/revisions\/676"}],"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=675"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}