lovell / sharp

High performance Node.js image processing, the fastest module to resize JPEG, PNG, WebP, AVIF and TIFF images. Uses the libvips library.
https://sharp.pixelplumbing.com
Apache License 2.0
29.31k stars 1.3k forks source link

.toBuffer() / .toArray() / .toFile() seems to affect unrelated Buffer instance #4266

Open stefan-girlich opened 1 week ago

stefan-girlich commented 1 week ago

Question about an existing feature

What are you trying to achieve?

I want to crop an image defined as base64 data. The original uncropped image should later be used to create a File object to be sent via FormData to a third-party service. For this purpose I create two separate Buffer instances from the same base64 string via Buffer.from().

Calling .toBuffer(), .toArray(), or .toFile() on the Sharp instance used for cropping seems to affect the original Buffer in a way that causes an error when sent to the third-party service. The service's responds with a generic error which provides no further insights.

My main question is: How is it possible that two independent buffers are linked? Is it related to buffers created via Buffer.from() being pooled?

I am not even sure if this is a Node.js issue or a Sharp issue. Thanks for your help and for any hint or idea!

When you searched for similar issues, what did you find that might be related?

Searched this issue tracker and Google for "extract changes original buffer", "modified buffer", "Node.js buffer re-used" and all sorts of variations and combinations.

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

const cropImage = (imageBuffer: Buffer, region: ImageRegion) => {
  sharp.cache(false)
  return sharp(imageBuffer)
    .extract({
      left: region.x,
      top: region.y,
      width: region.width,
      height: region.height,
    })
    .jpeg()
  // .toBuffer() // => fails; toArray() or toFile() also fails
  // .then((data) => `data:image/jpeg;base64,${data.toString('base64')}`)
}

const imageBase64DataString = imageBase64DataUri.replace(/^data:image\/jpeg;base64,/, '')
const firstBuffer = Buffer.from(imageBase64DataString, 'base64')

const secondBuffer = Buffer.from(imageBase64DataString, 'base64')
const regionBase64Uri = await cropImage(secondBuffer, region)

const file = new File([firstBuffer], 'image.jpg', { type: 'image/jpeg' })
const formData = new FormData()
formData.append('file', file, 'image.jpg')

// third-party API call - fails whenever toBuffer() is used, see above
const { error, fileMetadata } = await nhost.storage.upload({formData})

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

Any image. Black 4x4 JPEG I am currently using for testing:

data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEBLAEsAAD//gATQ3JlYXRlZCB3aXRoIEdJTVD/4gKwSUNDX1BST0ZJTEUAAQEAAAKgbGNtcwQwAABtbnRyUkdCIFhZWiAH6AALAA4ACwArAC5hY3NwQVBQTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9tYAAQAAAADTLWxjbXMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1kZXNjAAABIAAAAEBjcHJ0AAABYAAAADZ3dHB0AAABmAAAABRjaGFkAAABrAAAACxyWFlaAAAB2AAAABRiWFlaAAAB7AAAABRnWFlaAAACAAAAABRyVFJDAAACFAAAACBnVFJDAAACFAAAACBiVFJDAAACFAAAACBjaHJtAAACNAAAACRkbW5kAAACWAAAACRkbWRkAAACfAAAACRtbHVjAAAAAAAAAAEAAAAMZW5VUwAAACQAAAAcAEcASQBNAFAAIABiAHUAaQBsAHQALQBpAG4AIABzAFIARwBCbWx1YwAAAAAAAAABAAAADGVuVVMAAAAaAAAAHABQAHUAYgBsAGkAYwAgAEQAbwBtAGEAaQBuAABYWVogAAAAAAAA9tYAAQAAAADTLXNmMzIAAAAAAAEMQgAABd7///MlAAAHkwAA/ZD///uh///9ogAAA9wAAMBuWFlaIAAAAAAAAG+gAAA49QAAA5BYWVogAAAAAAAAJJ8AAA+EAAC2xFhZWiAAAAAAAABilwAAt4cAABjZcGFyYQAAAAAAAwAAAAJmZgAA8qcAAA1ZAAAT0AAACltjaHJtAAAAAAADAAAAAKPXAABUfAAATM0AAJmaAAAmZwAAD1xtbHVjAAAAAAAAAAEAAAAMZW5VUwAAAAgAAAAcAEcASQBNAFBtbHVjAAAAAAAAAAEAAAAMZW5VUwAAAAgAAAAcAHMAUgBHAEL/2wBDAP//////////////////////////////////////////////////////////////////////////////////////2wBDAf//////////////////////////////////////////////////////////////////////////////////////wgARCAAEAAQDAREAAhEBAxEB/8QAFAABAAAAAAAAAAAAAAAAAAAAAv/EABQBAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhADEAAAASf/xAAUEAEAAAAAAAAAAAAAAAAAAAAA/9oACAEBAAEFAn//xAAUEQEAAAAAAAAAAAAAAAAAAAAA/9oACAEDAQE/AX//xAAUEQEAAAAAAAAAAAAAAAAAAAAA/9oACAECAQE/AX//xAAUEAEAAAAAAAAAAAAAAAAAAAAA/9oACAEBAAY/An//xAAUEAEAAAAAAAAAAAAAAAAAAAAA/9oACAEBAAE/IX//2gAMAwEAAgADAAAAEB//xAAUEQEAAAAAAAAAAAAAAAAAAAAA/9oACAEDAQE/EH//xAAUEQEAAAAAAAAAAAAAAAAAAAAA/9oACAECAQE/EH//xAAUEAEAAAAAAAAAAAAAAAAAAAAA/9oACAEBAAE/EH//2Q==
lovell commented 1 week ago

Please provide a complete code sample, without the 3rd party dependency, that allows someone else to reproduce. This will need to include things like a concrete definition of the imageBase64DataUri and region variables as well as some error handling.