HTMLify

kikiki.html
Views: 25 | Author: amar
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Pixel → Lua Exporter</title>
  <style>
    body {
      margin: 0;
      padding: 0;
      display: flex;
      flex-direction: column;
      min-height: 100vh;
      background: #1e1e1e;
      color: #cfcfcf;
      font-family: Arial, sans-serif;
    }
    header, footer {
      text-align: center;
      padding: 1rem;
      background: #2d2d2d;
    }
    main {
      flex: 1;
      padding: 1rem;
      max-width: 700px;
      margin: 0 auto;
    }
    input, button, textarea, select {
      width: 100%;
      margin-top: 0.5rem;
      padding: 0.5rem;
      background: #2d2d2d;
      border: 1px solid #3c3c3c;
      color: #cfcfcf;
      font-size: 1rem;
      box-sizing: border-box;
    }
    label { display: block; margin-top: 1rem; }
    #original {
      display: block;
      margin: 1rem auto;
      max-width: 100%;
      border: 1px solid #3c3c3c;
    }
    #preview {
      display: block;
      margin: 1rem auto;
      image-rendering: pixelated;
      border: 1px solid #3c3c3c;
    }
    .slider-container {
      margin-top: 1rem;
      text-align: left;
      display: none;
    }
    .slider-container span {
      font-weight: bold;
    }
    #luaContainer {
      margin-top: 1rem;
      display: none;
    }
    textarea {
      width: 100%;
      height: 200px;
      background: #1e1e1e;
      color: #00ff90;
      font-family: monospace;
      font-size: 0.9rem;
      border: 1px solid #333;
      padding: 1rem;
      resize: vertical;
      line-height: 1.2;
    }
    #colorPickerBtn {
      background: none;
      border: none;
      cursor: pointer;
      width: auto;
      padding: 0;
      margin-top: 1rem;
    }
    #colorPickerBtn img {
      width: 32px;
      height: 32px;
    }
    footer {
      font-size: 0.9rem;
    }
  </style>
</head>
<body>
  <header>
    <h1>Pixel → Lua Exporter</h1>
  </header>
  <main>
    <label for="fileInput">Choose pixel image (PNG/GIF):</label>
    <input type="file" id="fileInput" accept="image/png, image/gif" />

    <img id="original" src="" alt="Original Upload" style="display:none;" />

    <div class="slider-container" id="sliderContainer">
      <label for="pixelSize">Pixel Size: <span id="pixelSizeLabel">1</span></label>
      <input type="range" id="pixelSize" min="1" max="50" value="1" />
    </div>

    <canvas id="preview" width="0" height="0"></canvas>

    <!-- Replace color picker with icon button -->
    <label>Pick Ignore Color:</label>
    <button id="colorPickerBtn">
      <img src="https://www.svgrepo.com/show/313906/eye-dropper-solid.svg" alt="Pick Color">
    </button>
    <input type="color" id="colorPicker" value="#000000" style="display: none;" />

    <div id="luaContainer">
      <label for="luaCode">Generated Lua</label>
      <textarea id="luaCode"></textarea>
    </div>

    <button id="downloadBtn" type="button" disabled>Export as .lua</button>
  </main>
  <footer>Made by Amar</footer>

  <script>
    const fileInput       = document.getElementById('fileInput');
    const originalImg     = document.getElementById('original');
    const pixelSize       = document.getElementById('pixelSize');
    const pixelSizeLabel  = document.getElementById('pixelSizeLabel');
    const sliderContainer = document.getElementById('sliderContainer');
    const preview         = document.getElementById('preview');
    const ctx             = preview.getContext('2d');
    const colorPicker     = document.getElementById('colorPicker');
    const colorPickerBtn  = document.getElementById('colorPickerBtn');
    const luaContainer    = document.getElementById('luaContainer');
    const luaCode         = document.getElementById('luaCode');
    const downloadBtn     = document.getElementById('downloadBtn');

    let img       = new Image();
    let imgName   = 'image';
    let origW     = 0;
    let origH     = 0;
    let loaded    = false;
    let ignoreHex = '000000';

    fileInput.addEventListener('change', e => {
      const file = e.target.files[0];
      if (!file) return;
      imgName = file.name.replace(/\.[^.]+$/, '');

      const url = URL.createObjectURL(file);
      img.src = url;
      originalImg.src = url;
      originalImg.style.display = 'block';

      img.onload = () => {
        origW = img.width;
        origH = img.height;
        loaded = true;
        sliderContainer.style.display = 'block';
        drawPixelated();
        updateLuaPreview();
        luaContainer.style.display = 'block';
        downloadBtn.disabled = false;
      };
    });

    pixelSize.addEventListener('input', () => {
      pixelSizeLabel.textContent = pixelSize.value;
      if (loaded) {
        drawPixelated();
        updateLuaPreview();
      }
    });

    // Icon button triggers hidden color input
    colorPickerBtn.addEventListener('click', () => {
      colorPicker.click();
    });

    colorPicker.addEventListener('input', () => {
      ignoreHex = colorPicker.value.slice(1);
      updateLuaPreview();
    });

    function drawPixelated() {
      const size = parseInt(pixelSize.value, 10);
      const tmpW = Math.ceil(origW / size);
      const tmpH = Math.ceil(origH / size);
      const tmp  = document.createElement('canvas');
      tmp.width  = tmpW;
      tmp.height = tmpH;
      const tctx = tmp.getContext('2d');
      tctx.imageSmoothingEnabled = false;
      tctx.drawImage(img, 0, 0, tmpW, tmpH);

      preview.width  = origW;
      preview.height = origH;
      ctx.imageSmoothingEnabled = false;
      ctx.clearRect(0,0,origW,origH);
      ctx.drawImage(tmp, 0, 0, tmpW, tmpH, 0, 0, origW, origH);
    }

    function rgbToHex(r, g, b) {
      return ((1<<24)|(r<<16)|(g<<8)|b).toString(16).slice(1);
    }

    function buildLuaString() {
      const size = parseInt(pixelSize.value, 10);
      const tmpW = Math.ceil(origW / size);
      const tmpH = Math.ceil(origH / size);
      const tmp  = document.createElement('canvas');
      tmp.width  = tmpW;
      tmp.height = tmpH;
      const tctx = tmp.getContext('2d');
      tctx.imageSmoothingEnabled = false;
      tctx.drawImage(img, 0, 0, tmpW, tmpH);

      const data = tctx.getImageData(0, 0, tmpW, tmpH).data;
      const rows = [];
      for (let y = 0; y < tmpH; y++) {
        const cols = [];
        for (let x = 0; x < tmpW; x++) {
          const i = (y*tmpW + x)*4;
          const a = data[i+3];
          const hex = a === 0
            ? 'ffffff'
            : rgbToHex(data[i], data[i+1], data[i+2]);
          cols.push(`"${hex}"`);
        }
        rows.push('      { ' + cols.join(', ') + ' },');
      }

      return [
        '--[[',
        `Title: ${imgName}`,
        'Platform: (unknown)',
        'url: ',
        ']]--',
        'return {',
        `  title = "${imgName}",`,
        `  name  = "${imgName}",`,
        `  width = ${tmpW},`,
        `  height= ${tmpH},`,
        `  ignore_colors = { "${ignoreHex}" },`,
        '  frames = {',
        '    {',
        ...rows,
        '    }',
        '  }',
        '}'
      ].join('\n');
    }

    function updateLuaPreview() {
      luaCode.value = buildLuaString();
    }

    downloadBtn.addEventListener('click', () => {
      const content = luaCode.value;
      const blob    = new Blob([content], { type: 'text/plain' });
      const url     = URL.createObjectURL(blob);
      const a       = document.createElement('a');
      a.href        = url;
      a.download    = `${imgName}.lua`;
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);
      URL.revokeObjectURL(url);
    });
  </script>
</body>
</html>

Comments