Changing image opacity with JS or CSS under mouse pointer?

As vals suggested, use an (arbitrary) mask. The following is a demonstration of a rectangular mask, although it can be very easily modified to be any shape that you wish. This version works on the latest versions of both Firefox and Chromium and allows for more complex shapes via SVG elements.

Note that this is very poor code. It will need to be written if you wish to use it in any project, but the idea is there.

Demo: http://jsfiddle.net/WK_of_Angmar/f8oe7hcq/

<!DOCTYPE html>
<html>
    <head>
        <script type="application/javascript">
            window.addEventListener("load", function() {
                var img = document.getElementsByTagName("image")[0];
                var imgPos = img.getBoundingClientRect();
                var imgX = imgPos.left;
                var imgY = imgPos.top;
                var rect = document.getElementsByTagName("rect")[1];
                var rectHalfWidth = rect.getAttribute("width") / 2;
                var rectHalfHeight = rect.getAttribute("height") / 2;
                img.addEventListener("mousemove", function(e) {
                    rect.setAttribute("x", e.clientX - imgX - rectHalfWidth);
                    rect.setAttribute("y", e.clientY - imgY - rectHalfHeight);
                    }, false);
            }, false);
        </script>
        <style>
            svg {
                width: 320px;
                height: 166px;
            }
            body {
                background-color: red;
                background-image: url("https://upload.wikimedia.org/wikipedia/commons/thumb/7/76/Mozilla_Firefox_logo_2013.svg/226px-Mozilla_Firefox_logo_2013.svg.png");
            }
            image:hover {
                mask: url("#cursorMask");
            }
        </style>
    </head>
    <body>
        <svg>
            <defs>
                <mask id="cursorMask" maskUnits="objectBoundingBox" maskContentUtils="objectBoundingBox">
                    <g>
                    <!-- the SECOND rect element is what determines the transparent area -->
                    <rect x="0" y="0" width="320" height="166" fill="#FFFFFF" />
                    <rect x="0" y="0" width="100" height="100" fill="#000000" />
                    </g>
                </mask>
            </defs>
        <image width="320" height="166" xlink:href="https://upload.wikimedia.org/wikipedia/commons/d/d4/Firefox-33-xfce.png" />
        </svg>
    </body>
</html>

You can get this using masking. It has limited support, but provides exactly what you want

The required CSS

#test {
    top: 0px;
    left: 0px;
    -webkit-mask-position: -20px -20px;
    -webkit-mask-size: 200px 400px;
    -webkit-mask-image: radial-gradient(circle, rgba(0, 0, 0, 0) 32px, rgba(0, 0, 0, 1) 38px);
    background-color: white;
    border: solid 1px red;
    width: 200px;
    height: 200px;
    background-image: url('http://placekitten.com/g/200/300');
}

body {
    background: repeating-linear-gradient(45deg, lightgreen 0px, white 50px);
}

and some scripting to get it moving

document.getElementById("test").addEventListener('mousemove', mouseMove, false);

function mouseMove (event)
{
    var ele = document.getElementById ('test');

    ele.style.webkitMaskPositionX = event.offsetX - 100 + "px";
    ele.style.webkitMaskPositionY = event.offsetY + 200 + "px";
}

demo - only webkit