{"id":672,"date":"2025-03-02T16:13:46","date_gmt":"2025-03-02T16:13:46","guid":{"rendered":"https:\/\/divbydev.com\/?page_id=672"},"modified":"2025-03-12T21:42:18","modified_gmt":"2025-03-12T21:42:18","slug":"image-pixel-shifter","status":"publish","type":"page","link":"https:\/\/divbydev.com\/index.php\/projects-2\/image-pixel-shifter\/","title":{"rendered":"Image Pixel Shifter"},"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>Image Pixel Shifter<\/title>\n  <style>\n    \/* CSS styles *\/\n    body {\n      font-family: Arial, sans-serif;\n      text-align: center;\n      padding: 20px;\n    }\n    canvas {\n      margin-top: 20px;\n      border: 1px solid #ccc;\n    }\n    input, select, button {\n      margin: 5px;\n    }\n  <\/style>\n<\/head>\n<body>\n\n  <input type=\"file\" id=\"upload\" accept=\"image\/*\">\n  <br>\n  <label for=\"redShift\">Red Shift:<\/label>\n  <input type=\"number\" id=\"redShift\" value=\"10\">\n  <br>\n  <label for=\"greenShift\">Green Shift:<\/label>\n  <input type=\"number\" id=\"greenShift\" value=\"10\">\n  <br>\n  <label for=\"blueShift\">Blue Shift:<\/label>\n  <input type=\"number\" id=\"blueShift\" value=\"10\">\n  <br>\n  <label>\n    <input type=\"radio\" name=\"direction\" value=\"row\" checked> Shift Rows\n  <\/label>\n  <label>\n    <input type=\"radio\" name=\"direction\" value=\"column\"> Shift Columns\n  <\/label>\n  <br>\n  <label for=\"glitchType\">Glitch Effect:<\/label>\n  <select id=\"glitchType\">\n    <option value=\"random\" selected>Random<\/option>\n    <option value=\"sine\">Sine Wave<\/option>\n  <\/select>\n  <br>\n  <button id=\"apply\">Apply Effect<\/button>\n  <button id=\"reset\">Reset Image<\/button>\n  <button id=\"clear\">Clear<\/button>\n  <button id=\"save\">Save Image<\/button>\n  <br>\n  <canvas id=\"canvas\"><\/canvas>\n\n  <script>\n    \/\/ JavaScript code\n    const upload = document.getElementById('upload');\n    const canvas = document.getElementById('canvas');\n    const ctx = canvas.getContext('2d');\n    const applyButton = document.getElementById('apply');\n    const resetButton = document.getElementById('reset');\n    const clearButton = document.getElementById('clear');\n    const saveButton = document.getElementById('save');\n\n    const redShiftInput = document.getElementById('redShift');\n    const greenShiftInput = document.getElementById('greenShift');\n    const blueShiftInput = document.getElementById('blueShift');\n    const glitchTypeSelect = document.getElementById('glitchType');\n\n    let img = new Image();\n    let originalImage = null; \/\/ Holds the original image data\n\n    \/\/ Load image on file selection and draw it on the canvas\n    upload.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        img = new Image();\n        img.onload = function() {\n          canvas.width = img.width;\n          canvas.height = img.height;\n          ctx.drawImage(img, 0, 0);\n          originalImage = ctx.getImageData(0, 0, canvas.width, canvas.height);\n        }\n        img.src = event.target.result;\n      }\n      reader.readAsDataURL(file);\n    });\n\n    \/\/ Apply glitch effect based on chosen type and direction\n    applyButton.addEventListener('click', function() {\n      \/\/ Reset canvas to original image first\n      if (originalImage) {\n        ctx.putImageData(originalImage, 0, 0);\n      } else {\n        ctx.drawImage(img, 0, 0);\n      }\n      \n      const direction = document.querySelector('input[name=\"direction\"]:checked').value;\n      const glitchType = glitchTypeSelect.value;\n      const redMax = parseInt(redShiftInput.value, 10) || 0;\n      const greenMax = parseInt(greenShiftInput.value, 10) || 0;\n      const blueMax = parseInt(blueShiftInput.value, 10) || 0;\n      \n      if (glitchType === 'random') {\n        if (direction === 'row') {\n          glitchRows(redMax, greenMax, blueMax);\n        } else {\n          glitchColumns(redMax, greenMax, blueMax);\n        }\n      } else if (glitchType === 'sine') {\n        if (direction === 'row') {\n          glitchRowsSine(redMax, greenMax, blueMax);\n        } else {\n          glitchColumnsSine(redMax, greenMax, blueMax);\n        }\n      }\n    });\n\n    \/\/ Reset the canvas to the originally loaded image\n    resetButton.addEventListener('click', function() {\n      if (originalImage) {\n        ctx.putImageData(originalImage, 0, 0);\n      }\n    });\n\n    \/\/ Clear file input, channel inputs, and canvas\n    clearButton.addEventListener('click', function(){\n      upload.value = \"\";\n      redShiftInput.value = \"\";\n      greenShiftInput.value = \"\";\n      blueShiftInput.value = \"\";\n      ctx.clearRect(0, 0, canvas.width, canvas.height);\n    });\n\n    \/\/ Save the current canvas as a PNG image\n    saveButton.addEventListener('click', function(){\n      const dataURL = canvas.toDataURL(\"image\/png\");\n      const link = document.createElement('a');\n      link.href = dataURL;\n      link.download = 'glitched-image.png';\n      document.body.appendChild(link);\n      link.click();\n      document.body.removeChild(link);\n    });\n\n    \/\/ Random glitch functions for rows and columns\n    function glitchRows(redMax, greenMax, blueMax) {\n      const width = canvas.width;\n      const height = canvas.height;\n      const imageData = ctx.getImageData(0, 0, width, height);\n      const data = imageData.data;\n      const newData = new Uint8ClampedArray(data);\n\n      for (let y = 0; y < height; y++) {\n        const randomShiftR = Math.floor(Math.random() * (2 * redMax + 1)) - redMax;\n        const randomShiftG = Math.floor(Math.random() * (2 * greenMax + 1)) - greenMax;\n        const randomShiftB = Math.floor(Math.random() * (2 * blueMax + 1)) - blueMax;\n        \n        for (let x = 0; x < width; x++) {\n          const destIndex = (y * width + x) * 4;\n          \n          let srcX_R = (x - randomShiftR + width) % width;\n          let srcIndex_R = (y * width + srcX_R) * 4;\n          newData[destIndex] = data[srcIndex_R];\n          \n          let srcX_G = (x - randomShiftG + width) % width;\n          let srcIndex_G = (y * width + srcX_G) * 4;\n          newData[destIndex + 1] = data[srcIndex_G + 1];\n          \n          let srcX_B = (x - randomShiftB + width) % width;\n          let srcIndex_B = (y * width + srcX_B) * 4;\n          newData[destIndex + 2] = data[srcIndex_B + 2];\n          \n          newData[destIndex + 3] = data[destIndex + 3];\n        }\n      }\n      ctx.putImageData(new ImageData(newData, width, height), 0, 0);\n    }\n\n    function glitchColumns(redMax, greenMax, blueMax) {\n      const width = canvas.width;\n      const height = canvas.height;\n      const imageData = ctx.getImageData(0, 0, width, height);\n      const data = imageData.data;\n      const newData = new Uint8ClampedArray(data);\n\n      for (let x = 0; x < width; x++) {\n        const randomShiftR = Math.floor(Math.random() * (2 * redMax + 1)) - redMax;\n        const randomShiftG = Math.floor(Math.random() * (2 * greenMax + 1)) - greenMax;\n        const randomShiftB = Math.floor(Math.random() * (2 * blueMax + 1)) - blueMax;\n        \n        for (let y = 0; y < height; y++) {\n          const destIndex = (y * width + x) * 4;\n          \n          let srcY_R = (y - randomShiftR + height) % height;\n          let srcIndex_R = (srcY_R * width + x) * 4;\n          newData[destIndex] = data[srcIndex_R];\n          \n          let srcY_G = (y - randomShiftG + height) % height;\n          let srcIndex_G = (srcY_G * width + x) * 4;\n          newData[destIndex + 1] = data[srcIndex_G + 1];\n          \n          let srcY_B = (y - randomShiftB + height) % height;\n          let srcIndex_B = (srcY_B * width + x) * 4;\n          newData[destIndex + 2] = data[srcIndex_B + 2];\n          \n          newData[destIndex + 3] = data[destIndex + 3];\n        }\n      }\n      ctx.putImageData(new ImageData(newData, width, height), 0, 0);\n    }\n\n    \/\/ Sine wave glitch functions for rows and columns\n    function glitchRowsSine(redMax, greenMax, blueMax) {\n      const width = canvas.width;\n      const height = canvas.height;\n      const imageData = ctx.getImageData(0, 0, width, height);\n      const data = imageData.data;\n      const newData = new Uint8ClampedArray(data);\n\n      for (let y = 0; y < height; y++) {\n        const sineShiftR = Math.floor(redMax * Math.sin((2 * Math.PI * y) \/ height));\n        const sineShiftG = Math.floor(greenMax * Math.sin((2 * Math.PI * y) \/ height));\n        const sineShiftB = Math.floor(blueMax * Math.sin((2 * Math.PI * y) \/ height));\n        \n        for (let x = 0; x < width; x++) {\n          const destIndex = (y * width + x) * 4;\n          \n          let srcX_R = (x - sineShiftR + width) % width;\n          let srcIndex_R = (y * width + srcX_R) * 4;\n          newData[destIndex] = data[srcIndex_R];\n          \n          let srcX_G = (x - sineShiftG + width) % width;\n          let srcIndex_G = (y * width + srcX_G) * 4;\n          newData[destIndex + 1] = data[srcIndex_G + 1];\n          \n          let srcX_B = (x - sineShiftB + width) % width;\n          let srcIndex_B = (y * width + srcX_B) * 4;\n          newData[destIndex + 2] = data[srcIndex_B + 2];\n          \n          newData[destIndex + 3] = data[destIndex + 3];\n        }\n      }\n      ctx.putImageData(new ImageData(newData, width, height), 0, 0);\n    }\n\n    function glitchColumnsSine(redMax, greenMax, blueMax) {\n      const width = canvas.width;\n      const height = canvas.height;\n      const imageData = ctx.getImageData(0, 0, width, height);\n      const data = imageData.data;\n      const newData = new Uint8ClampedArray(data);\n\n      for (let x = 0; x < width; x++) {\n        const sineShiftR = Math.floor(redMax * Math.sin((2 * Math.PI * x) \/ width));\n        const sineShiftG = Math.floor(greenMax * Math.sin((2 * Math.PI * x) \/ width));\n        const sineShiftB = Math.floor(blueMax * Math.sin((2 * Math.PI * x) \/ width));\n        \n        for (let y = 0; y < height; y++) {\n          const destIndex = (y * width + x) * 4;\n          \n          let srcY_R = (y - sineShiftR + height) % height;\n          let srcIndex_R = (srcY_R * width + x) * 4;\n          newData[destIndex] = data[srcIndex_R];\n          \n          let srcY_G = (y - sineShiftG + height) % height;\n          let srcIndex_G = (srcY_G * width + x) * 4;\n          newData[destIndex + 1] = data[srcIndex_G + 1];\n          \n          let srcY_B = (y - sineShiftB + height) % height;\n          let srcIndex_B = (srcY_B * width + x) * 4;\n          newData[destIndex + 2] = data[srcIndex_B + 2];\n          \n          newData[destIndex + 3] = data[destIndex + 3];\n        }\n      }\n      ctx.putImageData(new ImageData(newData, width, height), 0, 0);\n    }\n  <\/script>\n<\/body>\n<\/html>\n","protected":false},"excerpt":{"rendered":"<p>Stuff Image Pixel Shifter Red Shift: Green Shift: Blue Shift: Shift Rows Shift Columns Glitch Effect: RandomSine Wave Apply Effect Reset Image 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-672","page","type-page","status-publish"],"_links":{"self":[{"href":"https:\/\/divbydev.com\/index.php\/wp-json\/wp\/v2\/pages\/672","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=672"}],"version-history":[{"count":2,"href":"https:\/\/divbydev.com\/index.php\/wp-json\/wp\/v2\/pages\/672\/revisions"}],"predecessor-version":[{"id":731,"href":"https:\/\/divbydev.com\/index.php\/wp-json\/wp\/v2\/pages\/672\/revisions\/731"}],"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=672"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}