JSFiddle - React, Tailwind, and code Playground

by Imri Paloja

HTML

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/7.0.1/css/all.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/skeleton/2.0.4/skeleton.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.min.css">
<input type="file" id="imageInput" accept="image/*">

<canvas id="canvas"></canvas>

<div class="controls">
    <button onclick="rotate()">Rotate</button>
    <button onclick="grayscale()">Grayscale</button>
    <button onclick="reset()">Reset</button>
    <button onclick="save()">Save</button>
</div>

JavaScript

const input = document.getElementById('imageInput');
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');

let img = new Image();
let originalImageData = null;

input.addEventListener('change', (e) => {
  const file = e.target.files[0];
  if (!file) return;

  img.onload = () => {
    canvas.width = img.width;
    canvas.height = img.height;
    ctx.drawImage(img, 0, 0);
    originalImageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
  };

  img.src = URL.createObjectURL(file);
});

function rotate() {
  canvas.width = img.height;
  canvas.height = img.width;

  ctx.save();
  ctx.translate(canvas.width / 2, canvas.height / 2);
  ctx.rotate(Math.PI / 2);
  ctx.drawImage(img, -img.width / 2, -img.height / 2);
  ctx.restore();
}

function grayscale() {
  const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
  const data = imageData.data;

  for (let i = 0; i < data.length; i += 4) {
    const avg = (data[i] + data[i + 1] + data[i + 2]) / 3;
    data[i] = data[i + 1] = data[i + 2] = avg;
  }

  ctx.putImageData(imageData, 0, 0);
}

function reset() {
  if (originalImageData) {
    canvas.width = img.width;
    canvas.height = img.height;
    ctx.putImageData(originalImageData, 0, 0);
  }
}

function save() {
  canvas.toBlob(
    (blob) => {
      upload(blob);
    },
    'image/jpeg',
    0.9,
  );
}

function upload(blob) {
  const formData = new FormData();
  formData.append('image', blob, 'edited.jpg');

  fetch('/upload.php', {
    method: 'POST',
    body: formData,
  })
    .then((res) => res.json())
    .then((data) => console.log(data));
}