ThomasG2201
ThomasG2201

Reputation: 877

How to convert an image to an array of numbers (each number a pixel with its color) in javascript?

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.

Upvotes: 2

Views: 2650

Answers (1)

user3297291
user3297291

Reputation: 23372

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">

Upvotes: 2

Related Questions