Squash texture to fit geometry

I have a custom geometry with a texture like so:

My original image is:

Is it possible somehow to morph the texture so that every pixel is contained on the geometry? You can see that the 2 blue posts are cut off from the right hand side. I’d like it so that 100% of the original image is on the geometry, so in this example the bottom half would be squished a bit.

If that makes any sense at all.

I have zero photoshop skills but I’m wanting it to warp kinda like this:

image

In order to create the above, using the SVGLoader, I take a path and render a geometry like so:

const renderSVG = (svg) => {

    const svgGroup = new THREE.Group();
    svgGroup.scale.y *= -1;

    const svgData = loader.parse(svg);

    svgData.paths.forEach((path) => {
        const shapes = SVGLoader.createShapes(path);

        shapes.forEach((shape) => {
            const geometry = new THREE.ShapeGeometry( shape );
            setUV(geometry);
            const mesh = new THREE.Mesh( geometry, fillMaterial );
            svgGroup.add( mesh );
        });
    });

    const box = new THREE.Box3().setFromObject(svgGroup);
    const size = box.getSize(new THREE.Vector3());
    const yOffset = size.y / -2;
    const xOffset = size.x / -2;

    // Offset all of group's elements, to center them
    svgGroup.children.forEach((item) => {
        item.position.x = xOffset;
        item.position.y = yOffset;
    });
    svgGroup.rotateX(-Math.PI / 2);
    scene.add(svgGroup);
};

The setUV function is required in order to apply a texture (correct me if I’m wrong), I’m pretty sure prisoner849 wrote this:

const setUV = (geometry) =>{
    let pos = geometry.attributes.position;
    let b3 = new THREE.Box3().setFromBufferAttribute(pos);
    let size = new THREE.Vector3();
    b3.getSize(size);
    let uv = [];
    let v3 = new THREE.Vector2();
    for(let i = 0; i < pos.count; i++){
        v3.fromBufferAttribute(pos, i);
        v3.sub(b3.min).divide(size);
        uv.push(v3.x, v3.y);
    }
    geometry.setAttribute("uv", new THREE.Float32BufferAttribute(uv, 2));
}

That may be tricky to get looking good.

After the loop over pos, maybe try adding this:

let v2 = new THREE.Vector2();
for(let i=0;i<uv.length;i+2){
    v2.set(uv[i],uv[i+1]);
    v2.x-=.5;
    v2.y-=.5;
    let scl;
    if(abs(v2.x)>abs(v2.y))
       scl = (v2.x<0?-.5:.5)/v2.x;
    else
       scl = (v2.y<0?-.5:.5)/v2.y;
    v2.x *= scl;
    v2.y *= scl;
    uv[i]=v2.x + .5;
    uv[i+1]=v2.y + .5;
}