[SOLVED] Screenshot function. I Cannot specify a 'cutout area' of interest to be saved only?

Somehow I cannot specify a ‘cutout area’ of interest to be saved only (I need to do this in order make sure a server-saved canvas image is small enough [below 1024 kb] for saving {on my specific webprovider-space at least})

Here is my code-snip (which also builds-on/relates-to this issue;
[SOLVED] Capturing a screenshot alongside HTML/CSS UI):

{code-snip is from the screenshot.js / Screenshot.prototype.takeScreenshot-function}


var colorBuffer = this.renderTarget.colorBuffer;    var depthBuffer = this.renderTarget.depthBuffer;    

    // Fix for WebKit: https://github.com/playcanvas/developer.playcanvas.com/issues/268    // context must be cleared otherwise the first screenshot is always used    

    // https://stackoverflow.com/a/6722031/8648403    // Store the current transformation matrix

    this.context.save();

    // Use the identity matrix while clearing the canvas

    this.context.setTransform(1, 0, 0, 1, 0, 0);

    this.context.clearRect(0, 0, colorBuffer.width, colorBuffer.height);

    // Restore the transform

    this.context.restore();    var gl = this.app.graphicsDevice.gl;    var fb = this.app.graphicsDevice.gl.createFramebuffer();    var pixels = this.pixels;

   

    // We are accessing a private property here that has changed between

    // Engine v1.51.7 and v1.52.2

    var colorGlTexture = colorBuffer.impl ? colorBuffer.impl._glTexture : colorBuffer._glTexture;

    var depthGlTexture = depthBuffer.impl ? depthBuffer.impl._glTexture : depthBuffer._glTexture;

    gl.bindFramebuffer(gl.FRAMEBUFFER, fb);

    gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, colorGlTexture, 0);

    gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.TEXTURE_2D, depthGlTexture, 0);

    var sizeOfLeftRightMargs  =0; var sizeOfTopDownMargs  = 0; var colBuffWdt = colorBuffer.width; var colBuffHgt = colorBuffer.height;

    // Make 'Substract-to-720x405' margins

    var getWidth = window.innerWidth;

    if(getWidth>720){

        sizeOfLeftRightMargs = parseInt(Math.floor((getWidth-720)/2)); var getHeight = window.innerHeight; sizeOfTopDownMargs = parseInt(Math.floor((getHeight-405)/2));

        colBuffWdt = 720; colBuffHgt = 405;
    }

    gl.readPixels(sizeOfLeftRightMargs, sizeOfTopDownMargs, colBuffWdt, colBuffHgt, gl.RGBA, gl.UNSIGNED_BYTE, pixels);

   

    gl.deleteFramebuffer(fb);

    // first, create a new ImageData to contain our pixels

    var imgData = this.context.createImageData(colBuffWdt, colBuffHgt); // width x height

    var data = imgData.data;

   

    // Get a pointer to the current location in the image

    var palette = this.context.getImageData(sizeOfLeftRightMargs, sizeOfTopDownMargs, colBuffWdt, colBuffHgt); //x,y,w,h

    // Wrap your array as a Uint8ClampedArray

    palette.data.set(new Uint8ClampedArray(pixels)); // assuming values 0..255, RGBA, pre-mult.

And here is the output / err-msg:

Hi @Thomas_Due_Nielsen,

If you check the logs you are getting an error on the Uint8ClampedArray typed array. You are trying to add more values than it’s allowed to hold (typed arrays have a fixe size).

If you are having trouble working with Canvas operations in JavaScript try to find a library that can help you resize/trim an image in the browser, and use that in your project.

1 Like

Solved it myself - for those interested this function should be altered as well:

Screenshot.prototype.createNewRenderTexture = function() {

    var device = this.app.graphicsDevice;

    // Make sure we clean up the old textures first and remove

    // any references

    if (this.colorTexture && this.depthTexture && this.renderTarget) {

        var oldRenderTarget = this.renderTarget;

        var oldColorTexture = this.colorTexture;

        var oldDepthTexture = this.depthTexture;

       

        this.renderTarget = null;

        this.colorTexture = null;

        this.depthTexture = null;

       

        oldRenderTarget.destroy();

        oldColorTexture.destroy();

        oldDepthTexture.destroy();

    }

       

    // Create a new texture based on the current width and height

    var colorBuffer = new pc.Texture(device, {

        width: device.width,

        height: device.height,

        format: pc.PIXELFORMAT_R8_G8_B8_A8,

        autoMipmap: true

    });

   

    var depthBuffer = new pc.Texture(device, {

        format: pc.PIXELFORMAT_DEPTHSTENCIL,

        width: device.width,

        height: device.height,

        mipmaps: false,

        addressU: pc.ADDRESS_CLAMP_TO_EDGE,

        addressV: pc.ADDRESS_CLAMP_TO_EDGE

    });

    colorBuffer.minFilter = pc.FILTER_LINEAR;

    colorBuffer.magFilter = pc.FILTER_LINEAR;

    var renderTarget = new pc.RenderTarget({

        colorBuffer: colorBuffer,

        depthBuffer: depthBuffer,

        samples: 4 // Enable anti-alias

    });

   

    this.cameraEntity.camera.renderTarget = renderTarget;

   

    this.unScaledTextureWidth = device.width;

    this.unScaledTextureHeight = device.height;

   

    this.colorTexture = colorBuffer;

    this.depthTexture = depthBuffer;

    this.renderTarget = renderTarget;

   

    var cb = this.renderTarget.colorBuffer;

   

    if (!this.canvas) {

        // Create a canvas context to render the screenshot to

        this.canvas = window.document.createElement('canvas');

        this.context = this.canvas.getContext('2d');

    }

    this.canvas.width = cb.width;

    this.canvas.height = cb.height;

    // The render is upside down and back to front so we need to correct it

    this.context.globalCompositeOperation = "copy";

    this.context.setTransform(1, 0, 0, 1, 0, 0);

    this.context.scale(1,-1);

    this.context.translate(0,-this.canvas.height);

        var sizeOfLeftRightMargs  =0; var sizeOfTopDownMargs  = 0; var colBuffWdt = colorBuffer.width; var colBuffHgt = colorBuffer.height;

    // Make 'Substract-to-720x405' margins

    var getWidth = window.innerWidth;

    if(getWidth>832){

        sizeOfLeftRightMargs = parseInt(Math.floor((getWidth-832)/2)); var getHeight = window.innerHeight; sizeOfTopDownMargs = parseInt(Math.floor((getHeight-468)/2));

        colBuffWdt = 832; colBuffHgt = 468;

        console.log("imgDAT:"+sizeOfLeftRightMargs+" :: "+sizeOfTopDownMargs+" :: "+colBuffWdt+" :: "+colBuffHgt+" :: ");

    }

   

    this.pixels = new Uint8Array(colBuffWdt * colBuffHgt * 4);

};
2 Likes