{"id":692,"date":"2025-03-09T06:15:51","date_gmt":"2025-03-09T06:15:51","guid":{"rendered":"https:\/\/divbydev.com\/?page_id=692"},"modified":"2025-03-12T21:43:53","modified_gmt":"2025-03-12T21:43:53","slug":"image-to-pixel-art-converter","status":"publish","type":"page","link":"https:\/\/divbydev.com\/index.php\/projects-2\/image-to-pixel-art-converter\/","title":{"rendered":"Image to Pixel Art Converter"},"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 to Pixel Art Converter<\/title>\n  <style>\n    body {\n      font-family: Arial, sans-serif;\n      margin: 20px;\n    }\n    #controls {\n      margin-bottom: 20px;\n    }\n    canvas {\n      border: 1px solid #ccc;\n      margin-top: 10px;\n    }\n  <\/style>\n<\/head>\n<body>\n  <div id=\"controls\">\n    <!-- File selector -->\n    <input type=\"file\" id=\"fileInput\" accept=\"image\/*\"><br><br>\n    <!-- Checkbox for aspect ratio -->\n    <label>\n      <input type=\"checkbox\" id=\"aspectRatio\" checked>\n      Maintain Aspect Ratio\n    <\/label><br>\n    <!-- Retro palette selection drop-down -->\n    <label>\n      Retro Palette:\n      <select id=\"paletteSelect\">\n        <option value=\"none\">None<\/option>\n        <option value=\"nes\">NES (Simplified)<\/option>\n        <option value=\"c64\">Commodore 64<\/option>\n        <option value=\"gb\">Game Boy<\/option>\n        <option value=\"pico8\">PICO-8<\/option>\n        <option value=\"cga\">CGA<\/option>\n        <option value=\"amiga\">Amiga (Simplified)<\/option>\n      <\/select>\n    <\/label><br><br>\n    <!-- Buttons -->\n    <button id=\"saveBtn\">Save New Image<\/button>\n    <button id=\"clearBtn\">Clear<\/button>\n  <\/div>\n  \n  <!-- Canvas to display the converted image -->\n  <canvas id=\"canvas\"><\/canvas>\n\n  <script>\n    const fileInput = document.getElementById('fileInput');\n    const saveBtn = document.getElementById('saveBtn');\n    const clearBtn = document.getElementById('clearBtn');\n    const aspectRatioCheckbox = document.getElementById('aspectRatio');\n    const paletteSelect = document.getElementById('paletteSelect');\n    const canvas = document.getElementById('canvas');\n    const ctx = canvas.getContext('2d');\n    let originalImage = null;\n    \n    \/\/ Predefined retro palettes.\n    const palettes = {\n      nes: [\"#7C7C7C\", \"#0000FC\", \"#4428BC\", \"#940084\", \"#A80020\", \"#881400\", \"#503000\", \"#007800\", \"#005800\", \"#004058\", \"#000000\", \"#FFFFFF\"],\n      c64: [\"#000000\", \"#FFFFFF\", \"#880000\", \"#AAFFEE\", \"#CC44CC\", \"#00CC55\", \"#0000AA\", \"#EEEE77\", \"#DD8855\", \"#664400\", \"#FF7777\", \"#333333\", \"#777777\", \"#AAFF66\", \"#0088FF\", \"#BBBBBB\"],\n      gb: [\"#0F380F\", \"#306230\", \"#8BAC0F\", \"#9BBC0F\"],\n      pico8: [\"#000000\", \"#1D2B53\", \"#7E2553\", \"#008751\", \"#AB5236\", \"#5F574F\", \"#C2C3C7\", \"#FFF1E8\", \"#FF004D\", \"#FFA300\", \"#FFEC27\", \"#00E436\", \"#29ADFF\", \"#83769C\", \"#FF77A8\", \"#FFCCAA\"],\n      cga: [\"#000000\", \"#00AA00\", \"#AA0000\", \"#AA5500\", \"#0000AA\", \"#00AAAA\", \"#AA00AA\", \"#AAAAAA\", \"#555555\", \"#55FF55\", \"#FF5555\", \"#FFFF55\", \"#5555FF\", \"#55FFFF\", \"#FF55FF\", \"#FFFFFF\"],\n      amiga: [\"#000000\", \"#1B1B1B\", \"#363636\", \"#4F4F4F\", \"#686868\", \"#818181\", \"#9A9A9A\", \"#B3B3B3\", \"#CCCCCC\", \"#E5E5E5\", \"#FFFFFF\", \"#FF0000\", \"#00FF00\", \"#0000FF\", \"#FFFF00\", \"#FF00FF\"]\n    };\n    \n    \/\/ Helper: Convert a hex color to an RGB object.\n    function hexToRgb(hex) {\n      hex = hex.replace(\/^#\/, '');\n      if (hex.length === 3) {\n        hex = hex.split('').map(ch => ch + ch).join('');\n      }\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    \/\/ Apply palette mapping: For each pixel, map its color to the nearest color in the selected palette.\n    function applyPaletteMapping(imageData, palette) {\n      const data = imageData.data;\n      const paletteColors = palette.map(hexToRgb);\n      for (let i = 0; i < data.length; i += 4) {\n        const r = data[i], g = data[i + 1], b = data[i + 2];\n        let closestColor = paletteColors[0];\n        let minDistance = Number.MAX_VALUE;\n        for (let j = 0; j < paletteColors.length; j++) {\n          const pr = paletteColors[j].r;\n          const pg = paletteColors[j].g;\n          const pb = paletteColors[j].b;\n          const distance = (r - pr) ** 2 + (g - pg) ** 2 + (b - pb) ** 2;\n          if (distance < minDistance) {\n            minDistance = distance;\n            closestColor = paletteColors[j];\n          }\n        }\n        data[i] = closestColor.r;\n        data[i + 1] = closestColor.g;\n        data[i + 2] = closestColor.b;\n      }\n      return imageData;\n    }\n    \n    \/\/ Update the canvas with pixel art conversion using current settings.\n    function updateCanvas() {\n      if (!originalImage) return;\n      \n      \/\/ Fixed pixelation factor: 10% of the original image dimensions.\n      const scaleDownFactor = 0.1;\n      let width = originalImage.width * scaleDownFactor;\n      let height = originalImage.height * scaleDownFactor;\n      \n      if (!aspectRatioCheckbox.checked) {\n        width = 50;\n        height = 50;\n      }\n      \n      \/\/ Create an offscreen canvas for low-resolution drawing.\n      const offCanvas = document.createElement('canvas');\n      offCanvas.width = width;\n      offCanvas.height = height;\n      const offCtx = offCanvas.getContext('2d');\n      offCtx.imageSmoothingEnabled = false;\n      offCtx.drawImage(originalImage, 0, 0, width, height);\n      \n      \/\/ Get image data and apply palette mapping if a palette is selected.\n      let imageData = offCtx.getImageData(0, 0, width, height);\n      if (paletteSelect.value !== \"none\") {\n        const palette = palettes[paletteSelect.value];\n        imageData = applyPaletteMapping(imageData, palette);\n      }\n      offCtx.putImageData(imageData, 0, 0);\n      \n      \/\/ Scale up the low-res image onto the main canvas.\n      const scaleUpFactor = 10;\n      canvas.width = width * scaleUpFactor;\n      canvas.height = height * scaleUpFactor;\n      ctx.imageSmoothingEnabled = false;\n      ctx.clearRect(0, 0, canvas.width, canvas.height);\n      ctx.drawImage(offCanvas, 0, 0, canvas.width, canvas.height);\n    }\n    \n    \/\/ When a file is selected, load the image and automatically apply pixelation.\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 = updateCanvas;\n          originalImage.src = event.target.result;\n        };\n        reader.readAsDataURL(fileInput.files[0]);\n      }\n    });\n    \n    \/\/ Real-time preview: update canvas when aspect ratio or palette selection changes.\n    aspectRatioCheckbox.addEventListener('change', updateCanvas);\n    paletteSelect.addEventListener('change', updateCanvas);\n    \n    \/\/ Save the pixel art image.\n    saveBtn.addEventListener('click', () => {\n      if (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 = 'pixel_art.png';\n      link.href = canvas.toDataURL('image\/png');\n      link.click();\n    });\n    \n    \/\/ Clear all selections and reset the canvas.\n    clearBtn.addEventListener('click', () => {\n      fileInput.value = '';\n      aspectRatioCheckbox.checked = true;\n      paletteSelect.value = 'none';\n      canvas.width = canvas.height = 0;\n      originalImage = null;\n    });\n  <\/script>\n<\/body>\n<\/html>\n","protected":false},"excerpt":{"rendered":"<p>Stuff Image to Pixel Art Converter Maintain Aspect Ratio Retro Palette: NoneNES (Simplified)Commodore 64Game BoyPICO-8CGAAmiga (Simplified) Save New Image Clear<\/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-692","page","type-page","status-publish"],"_links":{"self":[{"href":"https:\/\/divbydev.com\/index.php\/wp-json\/wp\/v2\/pages\/692","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=692"}],"version-history":[{"count":1,"href":"https:\/\/divbydev.com\/index.php\/wp-json\/wp\/v2\/pages\/692\/revisions"}],"predecessor-version":[{"id":693,"href":"https:\/\/divbydev.com\/index.php\/wp-json\/wp\/v2\/pages\/692\/revisions\/693"}],"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=692"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}