简体   繁体   中英

How to read individual pixel transparency values from a user submitted PNG on the front-end?

I need to read the transparency value for each pixel of a user submitted PNG, on the front-end.

Right now I'm blocking the form submission and I convert the PNG in the file input to a FileReader object. Now I was thinking that I could simply read the transparency values out of that data. For example, I converted to ArrayBuffer and then to Uint8Array, and that's a large array of ints whose values range from 0-255, but it doesn't look like the right colors.

Then I read that you must actually display the PNG on an HTML5 canvas in order to do this.

PNG does not contain the raw image data, but is compressed. In order to decode it, you need to do some complex calculations. Load it into a <canvas> and let the browser do the decoding:

<canvas id="myCanvas"></canvas>
<input type="file" accept="image/png, image/gif, image/jpeg" id="myFileInput" />
<script>
    const canvas = document.getElementById('myCanvas');
    const context = canvas.getContext("2d"); 
    const fileInput = document.getElementById('myFileInput');

    fileInput.onchange = function(changeEvent) {
        const files = changeEvent.target.files;
        const file = files[0];
        const reader = new FileReader();
        reader.readAsDataURL(file);
        reader.onload = function(loadEvent){
            const image = new Image();
            image.src = loadEvent.target.result;
            canvas.width = image.width;
            canvas.height = image.height;
            context.drawImage(image, 0, 0);

            const imageData = context.getImageData(0, 0, image.width, image.height);
            console.log(imageData)
            // see https://stackoverflow.com/a/667074/17870699
        }  
    };
</script>

the png buffer don't hold the pixel data in a readable way, it's compressed so you can't read it like you would like to. you have to get the pixels somehow, the easiest straight forward way is to use createImageBitmap to turn it into a bitmap and then use the OffscreenCanvas to paint the bitmap and read it using getImageData This way you can read more than just pngs...

 // simulate getting a file you would get from eg file input (1x1 pixel) fetch('data:;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==').then(r => r.blob()).then(createImageBitmap).then(readData) /** @param {ImageBitmap} bitmap */ function readData (bitmap) { const { width: w, height: h } = bitmap const canvas = new OffscreenCanvas(w, h) const ctx = canvas.getContext('2d') ctx.drawImage(bitmap, 0, 0) const pixels = ctx.getImageData(0, 0, w, h).data // read alpha channel for (let i = 0; i < pixels.length; i += 4) { console.log(pixels[i + 3]) } }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM