Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to handle data down sampling after RangeError: Array buffer allocation failed #125

Open
usagibear opened this issue Feb 28, 2024 · 3 comments

Comments

@usagibear
Copy link

usagibear commented Feb 28, 2024

I ran into a range error due to my image being very large (50k x 30k pixels with CCITT T.6 compression). I was trying to down sample the 1D data array idfs[0].data I get from UTIF.decodeImage(e.target.result, ifds[0]), creating a new object and passing it to let rgba = UTIF.toRGBA8(). rgba is garbled when I use ctx.putImage(imageData, 0, 0). After I inspected some of the data in the idfs[0].data array, it looks like some values are undefined. Does idfs[0].data represent the raw image data? What could be the problem?

The object:

let smallifds = {
  data: downsample(ifds[0].data, width, height, windowWidth, windowHeight), 
  width: ifds[0].width / windowWidth, 
  height: ifds[0].height/ windowHeight
};

where downsample() takes the average of the data in a window/grid of windowWidth * windowHeight.

I tested with a smaller TIFF that works with ctx.putImage() and tried to scale it down by half by using the same method of down sampling the ifds[0].data but the data is garbled.

Thanks for your help!

@photopea
Copy link
Owner

photopea commented Feb 28, 2024

Since you are using CCITT, the raw image is 1 bit per pixel. So 1 Byte is 8 pixels. The size of idfs[0].data should be (width x height) / 8 Bytes. Are you sure your downsample method can process this raw image?

@usagibear
Copy link
Author

usagibear commented Feb 28, 2024

For the small image I have, its resolution is 1771 * 1220 (width * height). By the formula you mentioned, it should be 270077.5 = (1771 * 1220) / 8. However, when I do ifds[0].data.length, I get 270840 instead.

The way I am down sampling may also be the problem:

// Get the average sum of a window of values
const avgArr = (arr, wWidth, wHeight) => {
  let sum = 0;
  let count = 0;
  for (let y = 0; y < wHeight; y++) {
    for (let x = 0; x < windowWidth; x++) {
      count++;
      sum += arr[y * wWidth + x];
    }
  }
  return sum / count;
};

// wWidth: window width
// wHeight: window height
const downSample = (src, width, height, wWidth, wHeight) => {
  let dst = [];
  let hBlk = height / wHeight; // height block
  let wBlk = width / wWidth; // width block
  let blk = wHeight * wWidth; // block

  for (let zh = 0; zh < hBlk; zh++) {
    for (let zw = 0; zw < wBlk; zw++) {
      let subset = [];
      for (let y = 0; y < wHeight; y++) {
        for(let x = 0; x < wWidth; x++) {
          subset = subset.concat([src[zh * wBlk * blk + zw * wWidth + y * width + wWidth * x]]);
        }
      let avgValueResult = avgValue(subset, wWidth, wHeight);
      dst = dst.concat([avgValueResult]);
    }
  }

  return dst;
};

@photopea
Copy link
Owner

I think the number of bytes per line of pixels is rounded to a whole number of bytes.

Each line contains 1771 pixels, which is 221.375 Bytes, but it is rounded to 222 Bytes. So you should have 222 x 1220 = 270840 Bytes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants