2

so basically I upload an image via input of type file and I've a function that reads the content of the file. I suppose every given file is a PNG file.

Here is my function:

const handleFile = (e: Event) => {
  const target = e.target as HTMLInputElement;
  const files = target.files;
  if (files && files.length > 0) {
    const file: File = files[0];
    console.log("file =", file);

    var reader = new FileReader();
    reader.readAsArrayBuffer(file);
    reader.onloadend = function (evt: ProgressEvent<FileReader>) {
      if (evt.target!.readyState === FileReader.DONE) {
        const arrayBuffer = evt.target!.result as ArrayBuffer;
        const array = new Uint8Array(arrayBuffer);
        console.log("array =", array);
        console.log("array.length =", array.length);
        console.log("array.byteLength =", array.byteLength);
      }
    };
  }
};

For my tests, I use a 16x16 image (the stone block in Minecraft) named stone.png. Here is the result in the console:

array = Uint8Array(215) [137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 0, 16, 0, 0, 0, 16, 8, 6, 0, 0, 0, 31, 243, 255, 97, 0, 0, 0, 158, 73, 68, 65, 84, 56, 203, 133, 83, 65, 18, 0, 49, 4, 243, 92, 15, 112, 239, 19, 60, 185, 123, 98, 210, 52, 186, 7, 195, 152, 18, 34, 181, 204, 220, 104, 107, 173, 29, 17, 59, 34, 58, 118, 247, 35, 135, 102, 21, 96, 1, 63, 42, 115, 247, 110, 86, 111, 13, 81, 16, 137, 145, 167, …][0 … 99]0: 1371: 802: 783: 714: 135: 106: 267: 108: 09: 010: 011: 1312: 7313: 7214: 6815: 8216: 017: 018: 019: 1620: 021: 022: 023: 1624: 825: 626: 027: 028: 029: 3130: 24331: 25532: 9733: 034: 035: 036: 15837: 7338: 6839: 6540: 8441: 5642: 20343: 13344: 8345: 6546: 1847: 048: 4949: 450: 24351: 9252: 1553: 11254: 23955: 1956: 6057: 18558: 12359: 9860: 21061: 5262: 18663: 764: 19565: 15266: 1867: 3468: 18169: 20470: 22071: 10472: 10773: 17374: 2975: 1776: 5977: 3478: 5879: 11880: 24781: 3582: 13583: 10284: 2185: 9686: 187: 6388: 4289: 11590: 24791: 11092: 8693: 11194: 1395: 8196: 1697: 13798: 14599: 167[100 … 199][200 … 214]buffer: ArrayBuffer(215)  byteLength: 215byteOffset: 0length: 215Symbol(Symbol.toStringTag): "Uint8Array"[[Prototype]]: TypedArray
array.length = 215
array.byteLength = 215

My question is... How do I interpret those numbers? I want to be able to take each individual pixel in the image and extract its hexadecimal color.

Am I doing well or should I do something else?

NOTES : the image is 255 B and it says "32-bit color" but I don't know what that means.

ThomasG2201
  • 676
  • 6
  • 25
  • Group three numbers at a time to give you an RGB colour, and [then convert that to a hex](https://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb). – Andy May 23 '22 at 18:25
  • PNG is a compressed format, you can't just interpret it's bytes as an array of pixels. You should use a PNG parser library such as [this one](https://github.com/arian/pngjs) for example. It has a `getRGBA8Array` method that could probably fit your need. And 32-bit color means pixels contain 8 bits for red green and blue colors + 8 bits for transparency (alpha) – axelmln May 23 '22 at 18:52

1 Answers1

2

There might be an easier way, but you could:

  • Load the file as a data URL
  • Use the loaded data URL as an img source
  • Draw the image to a canvas
  • Use getImageData to get an array of RGBA values

In the example below, you can select your small .png file and you will see an array of numbers being logged to the console.

The way to read that array is:

  • Every 4 numbers represent a pixel's Red, Green, Blue and Alpha value
  • Pixels are logged from left to right, top to bottom

If you need a single pixel, you can either slice a part of the image data array, or use the getImageData call directly.

const handleFile = (e) => {
  const [ file ] = e.target.files;
  
  if (file) {
    const reader = new FileReader();
    
    reader.addEventListener("load", e => {
      const img = document.createElement("img");
      img.addEventListener("load", e => {
        const cvs = document.createElement("canvas");
        const ctx = cvs.getContext("2d");
        ctx.drawImage(img, 0, 0);
        
        console.log(ctx.getImageData(0, 0, img.width, img.height));
      });
      
      img.src = e.target.result
    }, false);
    
    reader.readAsDataURL(file);
  }
};

document.querySelector("input").addEventListener("change", handleFile);
<input type="file">
user3297291
  • 22,592
  • 4
  • 29
  • 45