{"id":608,"date":"2024-10-06T18:16:01","date_gmt":"2024-10-06T17:16:01","guid":{"rendered":"https:\/\/divbydev.com\/?page_id=608"},"modified":"2025-03-12T21:42:04","modified_gmt":"2025-03-12T21:42:04","slug":"glitch-effect-generator","status":"publish","type":"page","link":"https:\/\/divbydev.com\/index.php\/projects-2\/glitch-effect-generator\/","title":{"rendered":"Glitch Effect Generator"},"content":{"rendered":"\n<p>The Glitch Effect Generator is a browser-based tool that allows users to apply various glitch effects to images. Users can upload an image, apply glitch intensity, RGB channel shifts, chromatic aberration, or scan line distortion, and download the result directly from the browser. The tool provides different glitch presets, making it easy to achieve different visual styles quickly.<\/p>\n\n\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\">\n  <title>Glitch Effect Generator<\/title>\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n  <style>\n    \/* Minimal styling *\/\n    body {\n      font-family: Arial, sans-serif;\n      margin: 20px;\n    }\n    .container {\n      max-width: 600px;\n      margin: 0 auto;\n    }\n    input, button, select, label {\n      margin: 5px;\n    }\n    canvas {\n      border: 1px solid #ccc;\n      display: block;\n      margin-top: 20px;\n    }\n  <\/style>\n<\/head>\n<body>\n  <div class=\"container\">\n    <!-- File input -->\n    <div>\n      <input type=\"file\" id=\"file-input\" accept=\"image\/*\">\n    <\/div>\n    <!-- Glitch intensity as a secure numerical input -->\n    <div>\n      <label for=\"intensity-input\">Glitch Intensity (%):<\/label>\n      <input type=\"number\" id=\"intensity-input\" min=\"0\" max=\"100\" value=\"50\" required>\n    <\/div>\n    <!-- Option to add scan lines -->\n    <div>\n      <input type=\"checkbox\" id=\"scan-lines-checkbox\">\n      <label for=\"scan-lines-checkbox\">Add Scan Lines<\/label>\n    <\/div>\n    <!-- Option to apply channel separation -->\n    <div>\n      <input type=\"checkbox\" id=\"channel-sep-checkbox\">\n      <label for=\"channel-sep-checkbox\">Apply Channel Separation<\/label>\n      <span id=\"channel-direction-options\" style=\"display:none;\">\n        <input type=\"radio\" name=\"channel-direction\" id=\"dir-horizontal\" value=\"horizontal\" checked>\n        <label for=\"dir-horizontal\">Horizontal<\/label>\n        <input type=\"radio\" name=\"channel-direction\" id=\"dir-vertical\" value=\"vertical\">\n        <label for=\"dir-vertical\">Vertical<\/label>\n      <\/span>\n    <\/div>\n    <!-- Action buttons -->\n    <div>\n      <button id=\"apply-button\">Apply Glitch<\/button>\n      <button id=\"clear-button\">Clear<\/button>\n      <button id=\"save-button\">Save Image<\/button>\n    <\/div>\n    <!-- Canvas for output -->\n    <canvas id=\"canvas\"><\/canvas>\n  <\/div>\n\n  <script>\n    document.addEventListener('DOMContentLoaded', function() {\n      \/\/ Get element references\n      const fileInput = document.getElementById('file-input');\n      const intensityInput = document.getElementById('intensity-input');\n      const scanLinesCheckbox = document.getElementById('scan-lines-checkbox');\n      const channelSepCheckbox = document.getElementById('channel-sep-checkbox');\n      const channelDirectionOptions = document.getElementById('channel-direction-options');\n      const applyButton = document.getElementById('apply-button');\n      const clearButton = document.getElementById('clear-button');\n      const saveButton = document.getElementById('save-button');\n      const canvas = document.getElementById('canvas');\n      const ctx = canvas.getContext('2d');\n      \n      let originalImage = null;\n      \n      \/\/ Show\/hide channel direction options when channel separation checkbox changes\n      channelSepCheckbox.addEventListener('change', () => {\n        channelDirectionOptions.style.display = channelSepCheckbox.checked ? 'inline' : 'none';\n      });\n      \n      \/\/ Handle file selection\n      fileInput.addEventListener('change', function() {\n        const file = fileInput.files[0];\n        if (file && file.type.startsWith('image\/')) {\n          const reader = new FileReader();\n          reader.onload = function(e) {\n            const img = new Image();\n            img.onload = function() {\n              originalImage = img;\n              canvas.width = img.width;\n              canvas.height = img.height;\n              ctx.drawImage(img, 0, 0);\n            };\n            img.onerror = () => alert(\"Error loading image. Please try another file.\");\n            img.src = e.target.result;\n          };\n          reader.onerror = () => alert(\"Error reading file. Please try again.\");\n          reader.readAsDataURL(file);\n        } else {\n          alert(\"Please select a valid image file.\");\n        }\n      });\n      \n      \/\/ Main glitch effect function\n      function applyGlitchEffect() {\n        if (!originalImage) return;\n        \/\/ Reset canvas to original image\n        ctx.drawImage(originalImage, 0, 0);\n        const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);\n        const data = imageData.data;\n        const intensity = parseInt(intensityInput.value); \/\/ 0 to 100\n        \n        \/\/ Main pixel displacement glitch effect\n        for (let i = 0; i < data.length; i += 4) {\n          if (Math.random() < intensity \/ 100) {\n            const shift = Math.floor((Math.random() - 0.5) * intensity * 5);\n            const targetIndex = i + shift * 4;\n            if (targetIndex >= 0 && targetIndex < data.length) {\n              data[i]     = data[targetIndex];     \/\/ Red\n              data[i + 1] = data[targetIndex + 1];   \/\/ Green\n              data[i + 2] = data[targetIndex + 2];   \/\/ Blue\n              \/\/ Alpha remains unchanged\n            }\n          }\n        }\n        \n        \/\/ If scan lines enabled, apply scan lines effect\n        if (scanLinesCheckbox.checked) {\n          applyScanLines(data, canvas.width);\n        }\n        \n        \/\/ If channel separation enabled, apply channel separation effect\n        if (channelSepCheckbox.checked) {\n          const direction = document.querySelector('input[name=\"channel-direction\"]:checked').value;\n          applyChannelSeparation(data, canvas.width, canvas.height, direction);\n        }\n        \n        ctx.putImageData(imageData, 0, 0);\n      }\n      \n      \/\/ Apply scan lines: darken every 5th row\n      function applyScanLines(data, width) {\n        for (let y = 0; y < canvas.height; y++) {\n          if (y % 5 === 0) {\n            for (let x = 0; x < width; x++) {\n              const i = (y * width + x) * 4;\n              data[i]     *= 0.5;\n              data[i + 1] *= 0.5;\n              data[i + 2] *= 0.5;\n            }\n          }\n        }\n      }\n      \n      \/\/ Apply channel separation: shifts red and blue channels relative to green.\n      \/\/ Direction: \"horizontal\" or \"vertical\".\n      function applyChannelSeparation(data, width, height, direction) {\n        const output = new Uint8ClampedArray(data); \/\/ copy\n        const offset = 10; \/\/ pixel offset for separation effect\n        if (direction === \"horizontal\") {\n          \/\/ For each row, shift red to the right and blue to the left.\n          for (let y = 0; y < height; y++) {\n            for (let x = 0; x < width; x++) {\n              const i = (y * width + x) * 4;\n              \/\/ Red channel: sample from pixel shifted right by offset\n              if (x + offset < width) {\n                const srcIndex = (y * width + (x + offset)) * 4;\n                output[i] = data[srcIndex];\n              }\n              \/\/ Blue channel: sample from pixel shifted left by offset\n              if (x - offset >= 0) {\n                const srcIndex = (y * width + (x - offset)) * 4;\n                output[i + 2] = data[srcIndex + 2];\n              }\n            }\n          }\n        } else if (direction === \"vertical\") {\n          \/\/ For each column, shift red downward and blue upward.\n          for (let y = 0; y < height; y++) {\n            for (let x = 0; x < width; x++) {\n              const i = (y * width + x) * 4;\n              \/\/ Red channel: sample from pixel shifted down by offset\n              if (y + offset < height) {\n                const srcIndex = ((y + offset) * width + x) * 4;\n                output[i] = data[srcIndex];\n              }\n              \/\/ Blue channel: sample from pixel shifted up by offset\n              if (y - offset >= 0) {\n                const srcIndex = ((y - offset) * width + x) * 4;\n                output[i + 2] = data[srcIndex + 2];\n              }\n            }\n          }\n        }\n        \/\/ Copy output back into original data array\n        for (let i = 0; i < data.length; i++) {\n          data[i] = output[i];\n        }\n      }\n      \n      applyButton.addEventListener('click', applyGlitchEffect);\n      \n      clearButton.addEventListener('click', () => {\n        originalImage = null;\n        ctx.clearRect(0, 0, canvas.width, canvas.height);\n        canvas.width = 0;\n        canvas.height = 0;\n        fileInput.value = '';\n        intensityInput.value = 50;\n        scanLinesCheckbox.checked = false;\n        channelSepCheckbox.checked = false;\n        document.getElementById('channel-direction-options').style.display = 'none';\n      });\n      \n      saveButton.addEventListener('click', () => {\n        if (!originalImage) return;\n        const link = document.createElement('a');\n        link.download = 'glitch-image.png';\n        link.href = canvas.toDataURL('image\/png');\n        link.click();\n      });\n    });\n  <\/script>\n<\/body>\n<\/html>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>The Glitch Effect Generator is a browser-based tool that allows users to apply various glitch effects to images. Users can upload an image, apply glitch intensity, RGB channel shifts, chromatic aberration, or scan line distortion, and download the result directly from the browser. The tool provides different glitch presets, making it easy to achieve different &#8230; <a title=\"Glitch Effect Generator\" class=\"read-more\" href=\"https:\/\/divbydev.com\/index.php\/projects-2\/glitch-effect-generator\/\" aria-label=\"Read more about Glitch Effect Generator\">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-608","page","type-page","status-publish"],"_links":{"self":[{"href":"https:\/\/divbydev.com\/index.php\/wp-json\/wp\/v2\/pages\/608","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=608"}],"version-history":[{"count":13,"href":"https:\/\/divbydev.com\/index.php\/wp-json\/wp\/v2\/pages\/608\/revisions"}],"predecessor-version":[{"id":728,"href":"https:\/\/divbydev.com\/index.php\/wp-json\/wp\/v2\/pages\/608\/revisions\/728"}],"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=608"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}