Yeah, avoid to both advance offsets and re-slice the buffer, it only gets confusing. I would write

function calculate(typedArray) {
  const view = new DataView(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength);
  let i = 0;
  // Skip 4 chars, they are for signature
  i += 4;

  while (i < view.byteLength) {
    // read length of the next block
    const blockLen = view.getUint16(i, false /* big endian */);

    // ensure correct format
    // index should be within buffer limits
    if (i + blockLen > view.byteLength) {
      throw new TypeError('Corrupt JPG, exceeded buffer limits');
    }
    // Every JPEG block must begin with a 0xFF
    if (view.getUint8(i + blockLen) !== 0xFF) {
      throw new TypeError('Invalid JPG, marker table corrupted');
    }

    // 0xFFC0 is baseline standard(SOF)
    // 0xFFC1 is baseline optimized(SOF)
    // 0xFFC2 is progressive(SOF2)
    const next = view.getUint8(i + blockLen + 1);
    if (next === 0xC0 || next === 0xC1 || next === 0xC2) {
      return extractSize(view, i + blockLen + 5);
    }

    // move to the next block
    i += blockLen + 2;
  }

  throw new TypeError('Invalid JPG, no size found');
}

Notice that this code, which is a straightforward translation of the source, is slightly confusing and buggy:

  • i does not point to the start of the segment, but rather two bytes into the segment (after the marker)
  • the code skips the first dynamic segment (which, admittedly, is required to be an APP0 segment anyway)
  • the code assumes all segments to have a variable length specified in their header, and ignores standalone markers as well as fill bytes
  • the code may cause RangeError exceptions from accessing bytes beyond the end of the buffer, as it only checks for the past block to be within limits
Answer from Bergi on Stack Overflow
🌐
TutorialsPoint
tutorialspoint.com › nodejs › nodejs_buffer_readuint16be_method.htm
Node.js - Buffer.readUInt16BE() Method
The NodeJS Buffer.readUInt16BE() method helps in reading an unsigned 16-bit integer at a given offset from the buffer in big endian form.
🌐
Educative
educative.io › answers › what-is-readuint16be-in-the-nodejs-buffer-module
What is readUInt16BE() in the Node.js Buffer Module?
Buffer Module in Node.js provides ... readUInt16BE() is a method defined in the Buffer Class that reads a 16-bit, big-endian unsigned integer from the Buffer object starting from the specified offset....
🌐
GeeksforGeeks
geeksforgeeks.org › node.js › node-js-buffer-readuint16be-method
Node.js Buffer.readUInt16BE() Method - GeeksforGeeks
October 13, 2021 - The Buffer.readUInt16BE() method is an inbuilt application programming interface of class Buffer within the Buffer module which is used to read 16-bit value from an allocated buffer at a specified offset.
Top answer
1 of 1
1

Yeah, avoid to both advance offsets and re-slice the buffer, it only gets confusing. I would write

function calculate(typedArray) {
  const view = new DataView(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength);
  let i = 0;
  // Skip 4 chars, they are for signature
  i += 4;

  while (i < view.byteLength) {
    // read length of the next block
    const blockLen = view.getUint16(i, false /* big endian */);

    // ensure correct format
    // index should be within buffer limits
    if (i + blockLen > view.byteLength) {
      throw new TypeError('Corrupt JPG, exceeded buffer limits');
    }
    // Every JPEG block must begin with a 0xFF
    if (view.getUint8(i + blockLen) !== 0xFF) {
      throw new TypeError('Invalid JPG, marker table corrupted');
    }

    // 0xFFC0 is baseline standard(SOF)
    // 0xFFC1 is baseline optimized(SOF)
    // 0xFFC2 is progressive(SOF2)
    const next = view.getUint8(i + blockLen + 1);
    if (next === 0xC0 || next === 0xC1 || next === 0xC2) {
      return extractSize(view, i + blockLen + 5);
    }

    // move to the next block
    i += blockLen + 2;
  }

  throw new TypeError('Invalid JPG, no size found');
}

Notice that this code, which is a straightforward translation of the source, is slightly confusing and buggy:

  • i does not point to the start of the segment, but rather two bytes into the segment (after the marker)
  • the code skips the first dynamic segment (which, admittedly, is required to be an APP0 segment anyway)
  • the code assumes all segments to have a variable length specified in their header, and ignores standalone markers as well as fill bytes
  • the code may cause RangeError exceptions from accessing bytes beyond the end of the buffer, as it only checks for the past block to be within limits
🌐
Deno
docs.deno.com › api › node › buffer › ~ › Buffer.readUInt16BE
Buffer.readUInt16BE - buffer - Node documentation
import { Buffer } from 'node:buffer'; const buf = Buffer.from([0x12, 0x34, 0x56]); console.log(buf.readUInt16BE(0).toString(16)); // Prints: 1234 console.log(buf.readUInt16BE(1).toString(16)); // Prints: 3456
🌐
Stablelib
stablelib.com › functions › _stablelib_binary.readUint16BE.html
readUint16BE | StableLib
Reads 2 bytes from array starting at offset as big-endian unsigned 16-bit integer and returns it · Generated using TypeDoc
🌐
HowDev
how.dev › answers › what-is-the-bufferreaduint16be-method-in-nodejs
What is the Buffer.readUInt16BE() method in Node.js?
November 2, 2021 - The readUInt16BE() method is used in line 6 to get 16 bits from the index 1 in big-endian format.
Find elsewhere
🌐
GitHub
github.com › martinlindhe › formats › blob › master › parse › read.go
formats/parse/read.go at master · martinlindhe/formats
// ReadUint16be reads big endian Uint16 from `file` func ReadUint16be(file *os.File, pos int64) (uint16, error) { file.Seek(pos, os.SEEK_SET) var b uint16 · binary.Read(file, binary.BigEndian, &b) return b, nil · } · // ReadUint16le reads little endian Uint16 from `file` func ReadUint16le(file *os.File, pos int64) (uint16, error) { file.Seek(pos, os.SEEK_SET) var b uint16 ·
Author: martinlindhe
🌐
IBM
ibm.com › docs › en › datapower-gateway › 10.6.0
buf methods and properties - IBM Documentation
June 26, 2026 - var buf = new Buffer(4); buf[0] = 0x3; buf[1] = 0x4; buf[2] = 0x23; buf[3] = 0x42; console.log(buf,readUInt16BE(0)); // 0x0304 console.log(buf,readUInt16BE(1)); // 0x0423 console.log(buf,readUInt16BE(2)); // 0x2342
🌐
Node.js
nodejs.org › api › buffer.html
Buffer | Node.js v26.11.1 Documentation
buf.readUInt16BE([offset]) buf.readUInt16LE([offset]) buf.readUInt32BE([offset]) buf.readUInt32LE([offset]) buf.readUIntBE(offset, byteLength) buf.readUIntLE(offset, byteLength) buf.subarray([start[, end]]) buf.slice([start[, end]]) buf.swap16() buf.swap32() buf.swap64() buf.toJSON() ...
🌐
GitHub
github.com › fontello › ttf2woff › issues › 21
TypeError: arr.readUint16BE is not a function · Issue #21 · fontello/ttf2woff
February 2, 2022 - TypeError: arr.readUint16BE is not a function#21 · Copy link · aXlireza · opened · on Feb 2, 2022 · Issue body actions · When I use the module locally, it works just fine, but once I deploy to server, this error pops up The array is the same in both working and crashing environment, and yet, it crashes on server ·
Author: fontello
🌐
Millermedeiros
millermedeiros.github.io › mdoc › examples › node_api › doc › buffers.html
new Buffer(size) : nodejs API
var buf = new Buffer(4); buf[0] = 0x3; buf[1] = 0x4; buf[2] = 0x23; buf[3] = 0x42; console.log(buf.readUInt16BE(0)); console.log(buf.readUInt16LE(0)); console.log(buf.readUInt16BE(1)); console.log(buf.readUInt16LE(1)); console.log(buf.readUInt16BE(2)); console.log(buf.readUInt16LE(2)); // 0x0304 // 0x0403 // 0x0423 // 0x2304 // 0x2342 // 0x4223 ·
🌐
GitHub
github.com › tancredi › fantasticon › issues › 290
Node 10 compatibility · Issue #290 · tancredi/fantasticon
October 6, 2021 - root@aio:~# node --version v10.22.0 root@aio:~# fantasticon --version 1.2.3 root@aio:~# fantasticon in -o out arr.readUint16BE is not a function
Author: tancredi