0

Im trying to convert an image file to Int8Array. I have something like this:

public onFileChange(event) {
    const reader = new FileReader();
    reader.onload = () => {
      this.productImage = new Int8Array(reader.result);
    };
    
    reader.readAsArrayBuffer(event.target.files[0]);
    
  }

Where event is the uploaded image file. So how to put it in:

productImage: Int8Array;

I would use some help, thanks.

5
  • Is it not working? Commented Aug 17, 2020 at 17:29
  • Yeah. Im doing it in Angular. They dont comply. One is string | ArrayBuffer, the other is Iterable<number>. Commented Aug 17, 2020 at 17:41
  • You can make your own iterable that iterates on arrayBuffer using Dataview Commented Aug 18, 2020 at 17:48
  • Please clarify your problem, where does the error comes from? Your code is the way to go. Maybe your typescript IDE is set up to see FileReader#result as being a <string> since readAsText and readAsDataURL would indeed produce this, but that's just your IDE lying. Commented Aug 19, 2020 at 4:48
  • Not an Angular ninja myself, but Possible duplicate of stackoverflow.com/questions/52955710/… Commented Aug 19, 2020 at 5:00

1 Answer 1

0

You can use Dataview and iterate over it using an iterable

/**** Make Iterable ****/
//@arrayBuffer is the file arrayBuffer
var MakeMeIterable = function(arrayBuffer) {
  this.dataview = new DataView(arrayBuffer, 0);
  this.size = arrayBuffer.byteLength;
  this.index = 0;
}

// 1. Iterating construct like ... , for..of loop  initially calls this
MakeMeIterable.prototype[Symbol.iterator] = function() {
  // 2. Afterwards iterating construct utilises this object only for getting further values
  return {
    dataview: this.dataview,
    size: this.size,
    index: this.index,

    current: this.from,
    last: this.to,

    // 3. next() is called on each iteration by the other iterating constructs like ... , for..of loop
    next() {
      // 4. it should return the value as an object {done:.., value :...}
      if (this.index < this.size) {
        var result = this.dataview.getInt8(this.index);
        this.index += 1;
        return {
          done: false,
          value: result
        };
      } else {
        return {
          done: true
        };
      }
    }
  };
};

/**********************/
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id="input" type="file"></input>

<script>
  function readFile(f) {
    var reader = new FileReader();

    reader.onload = function() {
      var cursor = new MakeMeIterable(reader.result);
      this.productImage = cursor; //cursor <--iterable!

      /*
      //uncomment to have some fun in console
      for (let num of cursor) {
        console.log(num);
      }
      */

    };

    reader.onerror = function(e) {
      alert('Some error!');
      console.log("Error:", e);
    };
    reader.readAsArrayBuffer(f);
  }

  $(function() {
    $('#input').on("change", function(e) {
      var file = e.currentTarget.files[0];
      readFile(file);
    });
  });
</script>

Sign up to request clarification or add additional context in comments.

3 Comments

TypedArrays are iterable so all your code can be replaced with a more performant single liner new Uint8Array( await file.arrayBuffer() ). But that will probably not solve OP's problem anyway which is apparently more a type declaration issue which makes reader.result is treated as a string. (Also they wanted an Int8Array, not an Uint8)
Woa didnt know that they themselves are iterables! thanks for pointing about int8
using dataview seems a bit overkill. however, try new Uint8Array( new Response(file).arrayBuffer() ) if file.arrayBuffer() don't cut it

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.