HTMLify

image to lua
Views: 81 | 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 Generator</title>
  <style>
    input[type=range] {
      -webkit-appearance: none;
      appearance: none;
      width: 100%;
      margin-top: 0.5rem;
    }
    input[type=range]:focus { outline: none; }

    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;
    }
    label { display: block; margin-top: 1rem; }
    input, button, textarea {
      background: #2d2d2d;
      border: 1px solid #3c3c3c;
      color: #cfcfcf;
      font-size: 1rem;
      box-sizing: border-box;
    }
    input, textarea {
      width: 100%;
      padding: 0.5rem;
      margin-top: 0.5rem;
    }
    button {
      padding: 0.5rem;
      margin-top: 0.5rem;
      cursor: pointer;
    }

    .url-loader { display: flex; gap: 0.5rem; margin-top: 0.5rem; }
    .url-loader input[type=text] { flex: 1; }
    .url-loader button { flex: 0 0 80px; }

    #original { display: block; margin: 1rem auto; max-width: 100%; height: auto; border: 1px solid #3c3c3c; }
    #resolution, #outputResolution { text-align: center; margin-top: 0.25rem; color: #aaa; }
    .slider-container { margin-top: 1rem; display: none; }
    .slider-container span { font-weight: bold; }

    .canvas-container { position: relative; display: inline-block; margin: 1rem auto; border: 1px solid #3c3c3c; }
    #preview { display: block; max-width: 100%; height: auto; }

    #luaNameContainer { display: none; margin-top: 1rem; }
    #luaNameContainer .url-loader button { flex: 0 0 60px; }

    #colorPicker { width: 100%; height: 2.5rem; border: none; margin-top: 1rem; cursor: pointer; }
    #luaContainer { margin-top: 1rem; display: none; }
    textarea { height: 200px; font-family: monospace; font-size: 0.9rem; resize: vertical; line-height: 1.2; }
    #downloadBtn { width: 100%; }
    footer { font-size: 0.9rem; }
  </style>
</head>
<body>
  <header><h1>Pixel → Lua Generator</h1></header>
  <main>
    <!-- File upload -->
    <label for="fileInput">Choose pixel image:</label>
    <input type="file" id="fileInput" accept="image/*" />

    <!-- URL loader -->
    <label for="imageUrl">Or paste image URL:</label>
    <div class="url-loader">
      <input type="text" id="imageUrl" placeholder="https://example.com/image.jpg" />
      <button id="loadFromUrl">Load</button>
    </div>

    <!-- Lua name input (URL mode) -->
    <div id="luaNameContainer">
      <label for="luaName">Lua Filename (without extension):</label>
      <div class="url-loader">
        <input type="text" id="luaName" placeholder="custom_name" />
        <button id="setNameBtn">Set</button>
      </div>
    </div>

    <!-- Original preview -->
    <img id="original" src="" alt="Original Upload" style="display:none;" />
    <div id="resolution"></div>

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

    <!-- Canvas preview -->
    <div class="canvas-container" id="canvasContainer" style="display:none;">
      <canvas id="preview" width="0" height="0"></canvas>
    </div>
    <div id="outputResolution"></div>

    <!-- Color picker -->
    <label for="colorPicker">Pick Ignore Color:</label>
    <input type="color" id="colorPicker" value="#000000" />

    <!-- Lua output -->
    <div id="luaContainer">
      <label for="luaCode">Generated Lua</label>
      <textarea id="luaCode" readonly></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 imageUrl = document.getElementById('imageUrl');
    const loadFromUrl = document.getElementById('loadFromUrl');
    const originalImg = document.getElementById('original');
    const resolutionDiv = document.getElementById('resolution');
    const outputResDiv = document.getElementById('outputResolution');
    const pixelRange = document.getElementById('pixelRange');
    const pixelSizeLabel = document.getElementById('pixelSizeLabel');
    const sliderContainer = document.getElementById('sliderContainer');
    const canvasContainer = document.getElementById('canvasContainer');
    const preview = document.getElementById('preview');
    const ctx = preview.getContext('2d');
    const luaNameContainer = document.getElementById('luaNameContainer');
    const luaNameInput = document.getElementById('luaName');
    const setNameBtn = document.getElementById('setNameBtn');
    const colorPicker = document.getElementById('colorPicker');
    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, origH = 0;
    let loaded = false;
    let ignoreHex = '000000';
    let sourceUrl = '';

    function onImageLoaded() {
      origW = img.width; origH = img.height; loaded = true;
      sliderContainer.style.display = 'block';
      canvasContainer.style.display = 'inline-block';
      luaContainer.style.display = 'block';
      downloadBtn.disabled = false;
      originalImg.src = img.src; originalImg.style.display = 'block';
      resolutionDiv.textContent = `${origW}×${origH}`;
      luaNameContainer.style.display = sourceUrl ? 'block' : 'none';
      drawPixelated(); updateLuaPreview();
    }

    fileInput.addEventListener('change', e => {
      const file = e.target.files[0]; if (!file) return;
      imgName = file.name.replace(/\.[^.]+$/, ''); sourceUrl = '';
      img = new Image(); img.onload = onImageLoaded; img.src = URL.createObjectURL(file);
    });

    loadFromUrl.addEventListener('click', () => {
      const url = imageUrl.value.trim(); if (!url) return alert('Enter valid URL');
      imgName = url.split('/').pop().split('.')[0] || 'image'; sourceUrl = url;
      img = new Image(); img.crossOrigin = 'anonymous';
      img.onload = onImageLoaded; img.onerror = () => alert('Load failed.');
      img.src = url;
    });

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

    setNameBtn.addEventListener('click', () => {
      if (luaNameInput.value.trim()) imgName = luaNameInput.value.trim();
      updateLuaPreview();
    });

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

    function drawPixelated() {
      const size = +pixelRange.value;
      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);

      // update output resolution
      outputResDiv.textContent = `${tmpW}×${tmpH}`;
    }

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

    function buildLuaString() {
      const size = +pixelRange.value;
      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 alpha = data[i + 3];
          const hex = alpha === 0 ? 'ffffff' : rgbToHex(data[i], data[i + 1], data[i + 2]);
          cols.push(`"${hex}"`);
        }
        rows.push('      { ' + cols.join(', ') + ' },');
      }
      return [
        '--[[',
        `Title: ${imgName}`,
        `Platform: ${sourceUrl ? new URL(sourceUrl).hostname : 'local'}`,
        `url: ${sourceUrl}`,
        ']]--',
        '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 blob = new Blob([luaCode.value], { 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