Skip to content

Uint16Array copy from 16bit ushort raw Buffer read , But produce different result with API #3808

@jacobdong

Description

@jacobdong

Possible bug

Is this a possible bug in a feature of sharp, unrelated to installation?

  • Running npm install sharp completes without error.
  • Running node -e "require('sharp')" completes without error.

If you cannot confirm both of these, please open an installation issue instead.

Are you using the latest version of sharp?

  • I am using the latest version of sharp as reported by npm view sharp dist-tags.latest.

If you cannot confirm this, please upgrade to the latest version and try again before opening an issue.

If you are using another package which depends on a version of sharp that is not the latest, please open an issue against that package instead.

What is the output of running npx envinfo --binaries --system --npmPackages=sharp --npmGlobalPackages=sharp?

System:
OS: macOS 13.5.2
CPU: (8) arm64 Apple M1
Memory: 72.86 MB / 16.00 GB
Shell: 5.9 - /bin/zsh
Binaries:
Node: 16.19.1 - ~/.nvm/versions/node/v16.19.1/bin/node
Yarn: 1.22.19 - /usr/local/bin/yarn
npm: 9.6.4 - ~/.nvm/versions/node/v16.19.1/bin/npm
pnpm: 7.16.1 - ~/Library/pnpm/pnpm
npmPackages:
sharp: v0.32.6 => 0.32.6

What are the steps to reproduce?

  1. Read image by .raw({ depth: 'ushort' })
  2. Read px value by data.readUint16BE(pixelIndex);
  3. Copy to temp array
  4. construct a new sharp object to dump file

What is the expected behaviour?

the pic show same with api result
await sharp(path).toColorspace('grey16').png({progressive: false, force: true}).withMetadata({icc: 'p3'}).toFile('__local/16bit_copy.png');

Please provide a minimal, standalone code sample, without other dependencies, that demonstrates this problem

Please provide sample image(s) that help explain this problem

const assert16bitWrite = async (path: string) => {
  // Read the image as a 16-bit grayscale image
  const target = await sharp(path).toColourspace('grey16').raw({ depth: 'ushort' });
  const { data, info } = await target.toBuffer({ resolveWithObject: true });
  const { height, width } = info;

  console.log(info);

  // Create an array to store 16-bit grayscale values
  const uint16rawArray = [];
  for (let y = 0; y < height; y++) {
    for (let x = 0; x < width; x++) {
      const pixelIndex = (y * width + x) * info.channels * 2;
      const current = data.readUint16BE(pixelIndex);

      // In some scenarios, I might modify grayscale values, so I'm not directly using the conversion to grayscale API
      // .toColorspace('grey16').png({ progressive: false, force: true }).withMetadata({ icc: 'p3' }).toFile('__local/***.png')
      // For testing purposes, I'm simply reading and storing the grayscale values
      uint16rawArray.push(current)
    }
  }
  console.log(`Array length ${uint16rawArray.length} Expected length ${info.size / 2}`);

  // Save the 16-bit grayscale values back into an image
  await sharp(Uint16Array.from(uint16rawArray), {
    raw: {
      width: width,
      height: height,
      channels: 1,
    },
  })
    .toColorspace('grey16')
    .png({ progressive: false, force: true })
    .withMetadata({ icc: 'p3' })
    .toFile('__local/16bit_copy.png');
}

sample_01

input Image

16bit_std

output Image

16bit_copy

output by api Image

sharp(path).toColorspace('grey16').png({progressive: false, force: true}).withMetadata({icc: 'p3'})
grey16

sample_02

input Image

type_03

output Image

16bit_copy

output by api Image

sharp(path).toColorspace('grey16').png({progressive: false, force: true}).withMetadata({icc: 'p3'})
grey16

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions