HTML and JavaScript Made Easy: Create an Image Conversion Tool with ChatGPT

Learn How to Build a Simple Image Conversion Tool with Drag-and-Drop Interface using ChatGPT

ยท

10 min read

In this Blog I will share how I created a simple website using HTML and JS using ChatGPT. I will guide you how you can similarly give prompts and create your website with similar or slight modifications.

Live Website Link

This is a great project if you are applying for internships for a Web development role.

The website will have the following functionalities:

  1. Allows the user to select an image file by clicking on the "Click or drag and drop an image here" area or by clicking the hidden file input element.

  2. Displays the selected image below the dropzone, with the ability to set the JPEG quality via a range input element.

  3. Converts the selected image to a 500px wide JPEG format and displays it below the dropzone.

  4. Generates a data URI for the converted image and displays it in a text area element, allowing the user to copy and paste the image code elsewhere.

  5. Calculates and displays the size of the converted JPEG in bytes.

Prompt 1(Basic website):

User:

HTML and JavaScript for a page where a user can drag and drop an image onto a div and that image will then be turned into a 500px wide JPEG displayed below on the page, plus a text area containing a <img src= data URI>image that can be copied and pasted out.

Assistant:

To create an HTML page where a user can drag and drop an image onto a div, and then have that image converted to a 500px wide JPEG displayed below on the page, along with a textarea containing an <img src= data URI> image that can be copied and pasted out, you can use the following HTML and JavaScript code:

<!DOCTYPE html>
<html>
<head>
  <title>Drag and Drop Image</title>
  <style>
    #dropzone {
      width: 500px;
      height: 300px;
      border: 2px dashed #ccc;
      text-align: center;
      padding: 20px;
      margin-bottom: 20px;
    }
    #output {
      width: 500px;
      margin-bottom: 20px;
    }
    textarea {
      width: 500px;
      height: 100px;
    }
  </style>
</head>
<body>
  <div id="dropzone">Drag and drop an image here</div>
  <img id="output" src="" alt="Converted Image" />
  <textarea id="imgDataUri" readonly><textarea>

  <script>
    const dropzone = document.getElementById('dropzone');
    const output = document.getElementById('output');
    const imgDataUri = document.getElementById('imgDataUri');

    dropzone.addEventListener('dragover', (e) => {
      e.preventDefault();
      dropzone.style.backgroundColor = '#f0f0f0';
    });

    dropzone.addEventListener('dragleave', () => {
      dropzone.style.backgroundColor = '';
    });

    dropzone.addEventListener('drop', (e) => {
      e.preventDefault();
      dropzone.style.backgroundColor = '';

      const file = e.dataTransfer.files[0];
      if (file && file.type.startsWith('image/')) {
        const reader = new FileReader();
        reader.onload = (e) => {
          const img = new Image();
          img.onload = () => {
            const canvas = document.createElement('canvas');
            const ctx = canvas.getContext('2d');
            const aspectRatio = img.height / img.width;
            canvas.width = 500;
            canvas.height = 500 * aspectRatio;
            ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
            const dataUrl = canvas.toDataURL('image/jpeg');
            output.src = dataUrl;
            imgDataUri.value = `<img src="${dataUrl}" alt="Converted Image" />`;
          };
          img.src = e.target.result;
        };
        reader.readAsDataURL(file);
      } else {
        alert('Please drop an image file.');
      }
    });
  </script>
</body>
</html>

In this code, we define a div element with the ID dropzone that serves as the drop zone for the image. We also define an img element with the ID output to display the converted image and a textarea element with the ID imgDataUri to display the <img src= data URI> code.

The JavaScript code listens for the dragover, dragleave, and drop events on the dropzone element. When an image is dropped onto the dropzone, the code reads the image file, resizes it to 500px wide while maintaining the aspect ratio, converts it to a JPEG format, and displays it in the output image element. The data URI of the image is also displayed in the imgDataUri text area, ready to be copied and pasted out.


Prompt 2(Add Slider):

User:

Add a slider to control the JPEG quality from 0 to 100 - as the slider is moved the JPEG and the text area should both update

assistant: To add a slider that controls the JPEG quality and updates the JPEG and the textarea as the slider is moved, you can modify the existing code as follows:

<!DOCTYPE html>
<html>
<head>
  <title>Drag and Drop Image</title>
  <style>
    #dropzone {
      width: 500px;
      height: 300px;
      border: 2px dashed #ccc;
      text-align: center;
      padding: 20px;
      margin-bottom: 20px;
    }
    #output {
      width: 500px;
      margin-bottom: 20px;
    }
    textarea {
      width: 500px;
      height: 100px;
    }
  </style>
</head>
<body>
  <div id="dropzone">Drag and drop an image here</div>
  <label for="qualityRange">JPEG Quality: <span id="qualityValue">75</span></label>
  <input type="range" id="qualityRange" min="0" max="100" value="75" />
  <img id="output" src="" alt="Converted Image" />
  <textarea id="imgDataUri" readonly><textarea>

  <script>
    const dropzone = document.getElementById('dropzone');
    const output = document.getElementById('output');
    const imgDataUri = document.getElementById('imgDataUri');
    const qualityRange = document.getElementById('qualityRange');
    const qualityValue = document.getElementById('qualityValue');
    let imgSrc;

    dropzone.addEventListener('dragover', (e) => {
      e.preventDefault();
      dropzone.style.backgroundColor = '#f0f0f0';
    });

    dropzone.addEventListener('dragleave', () => {
      dropzone.style.backgroundColor = '';
    });

    dropzone.addEventListener('drop', (e) => {
      e.preventDefault();
      dropzone.style.backgroundColor = '';

      const file = e.dataTransfer.files[0];
      if (file && file.type.startsWith('image/')) {
        const reader = new FileReader();
        reader.onload = (e) => {
          imgSrc = e.target.result;
          updateImage();
        };
        reader.readAsDataURL(file);
      } else {
        alert('Please drop an image file.');
      }
    });

    qualityRange.addEventListener('input', () => {
      qualityValue.textContent = qualityRange.value;
      updateImage();
    });

    function updateImage() {
      if (!imgSrc) return;
      const img = new Image();
      img.onload = () => {
        const canvas = document.createElement('canvas');
        const ctx = canvas.getContext('2d');
        const aspectRatio = img.height / img.width;
        canvas.width = 500;
        canvas.height = 500 * aspectRatio;
        ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
        const quality = qualityRange.value / 100;
        const dataUrl = canvas.toDataURL('image/jpeg', quality);
        output.src = dataUrl;
        imgDataUri.value = `<img src="${dataUrl}" alt="Converted Image" />`;
      };
      img.src = imgSrc;
    }
  </script>
</body>
</html>

In this modified code, we added a label and an input element of type range with the ID qualityRange to create the slider for controlling the JPEG quality. The qualityValue span element displays the current value of the slider.

We also added an event listener for the input event on the qualityRange slider. When the slider value changes, the updateImage function is called to update the displayed image and the textarea content.

The updateImage function reads the current value of the slider, converts it to a quality factor between 0 and 1, and uses it to generate a new JPEG image with the specified quality. The toDataURL method accepts the second argument as the quality factor, which determines the quality of the generated JPEG image. The updated image is then displayed in the output image element, and the data URI of the image is displayed in the imgDataUri textarea.

The imgSrc variable is used to store the source of the original image, so we can regenerate the JPEG image with different quality settings as the slider is moved. The updateImage function is also called when a new image is dropped onto the dropzone, ensuring that the image is displayed with the current quality setting from the slider.


Prompt 3(Size of JPEG in Bytes):

User:

Update the design so each element is on a newline, and add a div that shows the size of the JPEG in bytes

assistant: To update the design so that each element is on a new line, and to add a div that shows the size of the JPEG in bytes, you can modify the existing code as follows:

<!DOCTYPE html>
<html>
<head>
  <title>Drag and Drop Image</title>
  <style>
    #dropzone {
      width: 500px;
      height: 300px;
      border: 2px dashed #ccc;
      text-align: center;
      padding: 20px;
      margin-bottom: 20px;
    }
    #output {
      width: 500px;
      margin-bottom: 20px;
    }
    textarea {
      width: 500px;
      height: 100px;
    }
    .container {
      margin-bottom: 20px;
    }
  </style>
</head>
<body>
  <div id="dropzone">Drag and drop an image here</div>
  <div class="container">
    <label for="qualityRange">JPEG Quality: <span id="qualityValue">75</span></label><br>
    <input type="range" id="qualityRange" min="0" max="100" value="75" />
  </div>
  <img id="output" src="" alt="Converted Image" /><br>
  <div class="container">
    <label for="imgDataUri">Image Data URI:</label><br>
    <textarea id="imgDataUri" readonly><textarea>
  </div>
  <div id="jpegSize">JPEG Size: 0 bytes</div>

  <script>
    const dropzone = document.getElementById('dropzone');
    const output = document.getElementById('output');
    const imgDataUri = document.getElementById('imgDataUri');
    const qualityRange = document.getElementById('qualityRange');
    const qualityValue = document.getElementById('qualityValue');
    const jpegSize = document.getElementById('jpegSize');
    let imgSrc;

    dropzone.addEventListener('dragover', (e) => {
      e.preventDefault();
      dropzone.style.backgroundColor = '#f0f0f0';
    });

    dropzone.addEventListener('dragleave', () => {
      dropzone.style.backgroundColor = '';
    });

    dropzone.addEventListener('drop', (e) => {
      e.preventDefault();
      dropzone.style.backgroundColor = '';

      const file = e.dataTransfer.files[0];
      if (file && file.type.startsWith('image/')) {
        const reader = new FileReader();
        reader.onload = (e) => {
          imgSrc = e.target.result;
          updateImage();
        };
        reader.readAsDataURL(file);
      } else {
        alert('Please drop an image file.');
      }
    });

    qualityRange.addEventListener('input', () => {
      qualityValue.textContent = qualityRange.value;
      updateImage();
    });

    function updateImage() {
      if (!imgSrc) return;
      const img = new Image();
      img.onload = () => {
        const canvas = document.createElement('canvas');
        const ctx = canvas.getContext('2d');
        const aspectRatio = img.height / img.width;
        canvas.width = 500;
        canvas.height = 500 * aspectRatio;
        ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
        const quality = qualityRange.value / 100;
        const dataUrl = canvas.toDataURL('image/jpeg', quality);
        output.src = dataUrl;
        imgDataUri.value = `<img src="${dataUrl}" alt="Converted Image" />`;
        const size = Math.round(dataUrl.length * 3 / 4); // Approximate size in bytes
        jpegSize.textContent = `JPEG Size: ${size}

---
**assistant**:  bytes`;
      };
      img.src = imgSrc;
    }
  </script>
</body>
</html>

In this modified code, we added <br> tags after the slider and the image to ensure that each element is on a new line. We also added a new div element with the ID jpegSize to display the size of the JPEG in bytes.

We introduced a new variable jpegSize to reference the div element that shows the size of the JPEG. In the updateImage function, we calculate the approximate size of the JPEG in bytes based on the length of the data URL. The size is then displayed in the jpegSize div.

Note that the calculated size is an approximation because the data URL is base64 encoded, and the actual size of the binary data is roughly 3/4 of the length of the base64 string. The size is rounded to the nearest whole number for display.

The container class is added to group elements and provide a margin at the bottom for better spacing. The label for the textarea is also added to improve accessibility.


Prompt 4(Add file to Website):

User:

Make it so clicking on the #dropzone div lets the user pick a file with a file picker

assistant: To allow the user to pick a file using a file picker when clicking on the #dropzone div, we can add an element to the HTML and trigger its click event when the #dropzone div is clicked. Here's the updated code:

<!DOCTYPE html>
<html>
<head>
  <title>Drag and Drop Image</title>
  <style>
    #dropzone {
      width: 500px;
      height: 300px;
      border: 2px dashed #ccc;
      text-align: center;
      padding: 20px;
      margin-bottom: 20px;
      cursor: pointer;
    }
    #output {
      width: 500px;
      margin-bottom: 20px;
    }
    textarea {
      width: 500px;
      height: 100px;
    }
    .container {
      margin-bottom: 20px;
    }
    #fileInput {
      display: none;
    }
  </style>
</head>
<body>
  <div id="dropzone">Click or drag and drop an image here</div>
  <input type="file" id="fileInput" accept="image/*">
  <!-- Rest of the code remains the same -->
  <!-- ... -->

  <script>
    const dropzone = document.getElementById('dropzone');
    const fileInput = document.getElementById('fileInput');
    // Rest of the code remains the same
    // ...

    dropzone.addEventListener('click', () => {
      fileInput.click();
    });

    fileInput.addEventListener('change', () => {
      const file = fileInput.files[0];
      if (file && file.type.startsWith('image/')) {
        const reader = new FileReader();
        reader.onload = (e) => {
          imgSrc = e.target.result;
          updateImage();
        };
        reader.readAsDataURL(file);
      } else {
        alert('Please select an image file.');
      }
    });

    // Rest of the code remains the same
    // ...
  </script>
</body>
</html>

In this updated code, we added an <input type="file">element with the ID fileInput to the HTML. The accept="image/*" attribute ensures that only image files.

Final App:

<!DOCTYPE html>
<html>
<head>
  <title>Drag and Drop Image</title>
  <style>
    #dropzone {
      width: 500px;
      height: 100px;
      border: 2px dashed #ccc;
      text-align: center;
      padding: 20px;
      margin-bottom: 20px;
    }
    #output {
      width: 500px;
      margin-bottom: 20px;
    }
    textarea {
      width: 500px;
      height: 100px;
    }
    .container {
      margin-bottom: 20px;
    }
    #fileInput {
      display: none;
    }
  </style>
</head>
<body>
  <div id="dropzone">Click or drag and drop an image here</div>
  <input type="file" id="fileInput" accept="image/*">
  <div class="container">
    <label for="qualityRange">JPEG Quality: <span id="qualityValue">75</span></label><br>
    <input type="range" id="qualityRange" min="0" max="100" value="75" />
  </div>
  <img id="output" src="" alt="Converted Image" /><br>
  <div class="container">
    <label for="imgDataUri">Image Data URI:</label><br>
    <textarea id="imgDataUri" readonly></textarea>
  </div>
  <div id="jpegSize">JPEG Size: 0 bytes</div>

  <script>
    const dropzone = document.getElementById('dropzone');
    const fileInput = document.getElementById('fileInput');
    dropzone.addEventListener('click', () => {
      fileInput.click();
    });

    fileInput.addEventListener('change', () => {
      const file = fileInput.files[0];
      if (file && file.type.startsWith('image/')) {
        const reader = new FileReader();
        reader.onload = (e) => {
          imgSrc = e.target.result;
          updateImage();
        };
        reader.readAsDataURL(file);
      } else {
        alert('Please select an image file.');
      }
    });
    const output = document.getElementById('output');
    const imgDataUri = document.getElementById('imgDataUri');
    const qualityRange = document.getElementById('qualityRange');
    const qualityValue = document.getElementById('qualityValue');
    const jpegSize = document.getElementById('jpegSize');
    let imgSrc;

    dropzone.addEventListener('dragover', (e) => {
      e.preventDefault();
      dropzone.style.backgroundColor = '#f0f0f0';
    });

    dropzone.addEventListener('dragleave', () => {
      dropzone.style.backgroundColor = '';
    });

    dropzone.addEventListener('drop', (e) => {
      e.preventDefault();
      dropzone.style.backgroundColor = '';

      const file = e.dataTransfer.files[0];
      if (file && file.type.startsWith('image/')) {
        const reader = new FileReader();
        reader.onload = (e) => {
          imgSrc = e.target.result;
          updateImage();
        };
        reader.readAsDataURL(file);
      } else {
        alert('Please drop an image file.');
      }
    });

    qualityRange.addEventListener('input', () => {
      qualityValue.textContent = qualityRange.value;
      updateImage();
    });

    function updateImage() {
      if (!imgSrc) return;
      const img = new Image();
      img.onload = () => {
        const canvas = document.createElement('canvas');
        const ctx = canvas.getContext('2d');
        const aspectRatio = img.height / img.width;
        canvas.width = 500;
        canvas.height = 500 * aspectRatio;
        ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
        const quality = qualityRange.value / 100;
        const dataUrl = canvas.toDataURL('image/jpeg', quality);
        output.src = dataUrl;
        imgDataUri.value = `<img src="${dataUrl}" alt="Converted Image" />`;
        const size = Math.round(dataUrl.length * 3 / 4); // Approximate size in bytes
        jpegSize.textContent = `JPEG Size: ${size.toLocaleString()} bytes`;
      };
      img.src = imgSrc;
    }
</script>
</body>
</html>

Thank u for Reading this. ๐Ÿ˜Š

ย