Search code examples
javascriptimagebitmap

Bitmatrix read as vertical is wrong | Javascript


I want to make a website to upload images, resize them to 32x128, convert them to hex bitmatrix with an Filter like dithering or Threshold. For testing I use image2cpp by javl. Reading my bitmatrix as horizontal works and it shows the correct horizontal image:

Working image:
correct horizontal image

Working code:

//Working Code
//Get Image from Canvas

    matrix = Array.from({ length: height }, (_, i) =>
      Array.from({ length: width }, (_, j) =>
        ctx.getImageData(j, i, 1, 1).data[0] > 0 ? 1 : 0
      )
    );
   
//Convert binary to hex
    return matrix
      .reduce((acc, row) => {
        acc += row.reduce((acc, value) => {
          acc += value > 0 ? "1" : "0";
          return acc;
        }, "");
        return acc;
      }, "")
      .match(/.{1,8}/g)
      .map((byte) => "0x" + parseInt(byte, 2).toString(16));
  

Now i want to read my bitmatrix as vertical.
For that I tried to transpose the matrix and convert it to hex.
But my wrong looks rotated and split up.
It should be the same as above.

Not working image:
vertical result

Not working code:

//read as vertical
//not working
    matrix = Array.from({ length: height }, (_, i) =>
      Array.from({ length: width }, (_, j) =>
        ctx.getImageData(j, i, 1, 1).data[0] > 0 ? 1 : 0
      )
    );

//new code
    matrix[0].map((_, colIndex) => matrix.map(row => row[colIndex]));

//same conversion as above
    return matrix
          .reduce((acc, row) => {
           ....


Solution

  • See the code snippet below for a working replacement for your matrix rotate. You were just missing the need to assign the results of your map() calls into a new variable.

    Also, I added a .padStart(2,"0") to the end of your bin to hex code, since image2cpp does not seem to work correctly if you don't pad out to 2 characters.

    let ctx = document.querySelector("canvas").getContext( "2d" )
    ctx.canvas.width = 32
    ctx.canvas.height = 128
    
    // Draw a shape on the canvas
    ctx.strokeStyle = "white"
    ctx.beginPath( )
    ctx.rect( 0, 0, 28, 124 )
    ctx.arc( 10, 16, 4, 0, 2 * Math.PI )
    ctx.stroke( )
    
    let str = ""
    for( let next of rotateBinaryToHex() ) {
      str += next
    }
    console.log( "Paste this into image2cpp and set size to 128 x 32 px")
    console.log(str)
    
    
    function rotateBinaryToHex( ) {
      let width = ctx.canvas.width;
      let height = ctx.canvas.height;
      let matrix = []
    
      //Get Image from Canvas
      matrix = Array.from({ length: height }, (_, i) =>
        Array.from({ length: width }, (_, j) => ctx.getImageData(j, i, 1, 1).data[0] > 0 ? 1 : 0 )
      );
    
    
      //NOTE New "new code" to rotate the matrix 90 degrees
      let rotatedMatrix = matrix[0].map((_, colIndex) => matrix.map(row => row[colIndex]));
    
    
      //Convert binary to hex
      // return matrix
      return rotatedMatrix
      .reduce((acc, row) => {
        acc += row.reduce((acc, value) => {
          acc += value > 0 ? "1" : "0";
          return acc;
        }, "");
        return acc;
      }, "")
      .match(/.{1,8}/g)
      // NOTE image2cpp does not seem to display data correctly if you don't pad out to 2 characters
      .map((byte) => "0x" + parseInt(byte, 2).toString(16).padStart(2,"0"));
    }
    body {
      background-color: gray;
    }
    
    canvas {
      box-shadow: 2px 2px 8px black;
    }
    <canvas></canvas>