Interference effects on image zoom

A playful exploration into the world of image rendering.

I recently discovered that pixel interference effects can occur by zooming in on gray image areas. This got me thinking: Can we construct an image that initially looks uniformly gray but reveals information on specific zoom levels? Is it maybe even possible to show different grayscale images depending on the zoom level?

The following tests show client-side generated images using the <canvas> element. However the image data is not manipulated during zoom - just the CSS transform: scale() property changes. The demos need pixel perfect sizes to work. Therefore the images could be too small or too big on some devices - I apologize.

Please also note that I do not have any prior knowledge in the field of image rendering. I was just playing around and documenting things I found interesting. I hope you find this little tour interesting as well :).

The interference effect

The first image is just a checkerboard pattern on pixel scale (this is clearly visible on 2x). When zooming in the image pixel grid and the screen pixel grid are misaligned creating interference effects in both dimensions. They are especially strong in the area of 0.5x, 0.25x, 0.1667x and 0.125x. These turn out to be the whole number parts of 1/2. This makes sense: For two adjacent screen pixels the distance of the image pixels is a multiple of 2 which locally creates a uniformly colored area.

[If you see this text your browser unfortunately does not support Javascript.]

Another observation about browser differences can be made here: In Chromium I can zoom smoothly at this microscopic scale, Firefox only allows zoom steps. Interestingly for every zoom step the image size is an integer multiple of 1/2 of the interference period. I do not know why. Also on Firefox for Android there are graphic glitches across the whole screen for some zoom levels. I guess this is a graphics driver issue of my device but I am not sure.

On Chromium the image is completely black on some zoom levels like 0.5x. However this bug does not occur when opening the image in a new tab and zooming to 0.5x.

For the second test I inverted the checkerboard pattern for some areas of the image. There are zoom levels like 1x where just parts of the border of the shape are visible. For other zoom levels like 0.5x the whole shape area is clearly visible.

[If you see this text your browser unfortunately does not support Javascript.]

Other types of colorings

Let's explore some other types of local colorings. I chose uniform gray and random pixel values for the next demo. As expected the gray area does not show any interference effects at all. The random area on the other hand has them but they are hardly visible. You can see them if you keep the rough slider at 1x and just move the fine slider.

[If you see this text your browser unfortunately does not support Javascript.]

Now let's combine different types of colorings. The random noise seems to be too different but a combination of checkerboard and gray could work. It does in fact: For 0.999x the difference is just barely visible on Firefox and invisible on Chromium.

[If you see this text your browser unfortunately does not support Javascript.]

To hide the remaining interference artifacts we bring the random noise back and add it to our color values. Now things start to get really interesting. Let's just look at the zoom levels 0.999x and 0.5x for the next two demos.

On 0.5x the square is sometimes visible and sometimes invisible. After a bit of testing I found out that it depends on the parity of the image width. I cannot explain it but I also do not find it implausible that these interference effects change drastically on size parity.

The real weirdness starts on 0.999x. On Firefox the square is visible for images smaller or equal to 500px in size and invisible for larger ones. I suppose Firefox uses different rendering techniques for different image sizes. On Chrome the square is visible if and only if it is also visible on 1x - this means it is visible for even image sizes and invisible for odd sizes.

[If you see this text your browser unfortunately does not support Javascript.]
[If you see this text your browser unfortunately does not support Javascript.]

Invisibility on 1x

It would be really cool to create an image that is invisible on 1x but appears on zoom. This did already work but just in Chromium. My first idea for this was to hide the interference area in a random area and match the grayscale level:

[If you see this text your browser unfortunately does not support Javascript.]

This does work on Firefox on my specific screen. The difference is however visible in other browsers and on Firefox on other devices.

To create a truly invisible interference area my next idea was to rearrange the pixels according to their color. This ensures equal color distribution inside and outside the interference area. It is however rather complicated to implement. The same effect can be achieved with random colors using uneven probabilities. For a dark pixel on the checkerboard we generate two random color values and take the smaller one. This is equivalent to imagining a neighboring light pixel and swapping their values if necessary.

Now the effect really works consistent across devices and screens! Try zooming to 0.5x for example.

[If you see this text your browser unfortunately does not support Javascript.]

Now if we think in terms of probability distributions this process can be easily generalized from hidden black-and-white to grayscale images. Try the following example on 0.5x. Unfortunately the interference patterns are only clearly visible in the center of the image as you can see at the end of the paint brush. (This is sometimes not the case on Chromium.)

[If you see this text your browser unfortunately does not support Javascript.]

It would be really cool if the whole area could be used for hidden images. However i think that is impossible. There are always spots of destructive interference and for 0.5x and its whole number parts these spots are already at the border of the image.

Using the following file picker you can try the effect yourself. I respect your privacy so all images are processed client-side. You can check that in the network tab in the debugging tools of your browser. Please choose a square image - implementing and exploring other aspect ratios is left as an idea to the reader.

[If you see this text your browser unfortunately does not support Javascript.]

Colored images

Since RGB displays have separate LEDs for the three color components this process should be easily generalizable to color images by just repeating it three times per pixel. It works, indeed (try 0.5x).

[If you see this text your browser unfortunately does not support Javascript.]

As above, you can try it yourself:

[If you see this text your browser unfortunately does not support Javascript.]

Ideas for future exploration

Many questions are left unanswered in this text. I chose to highlight some of them:

That's enough for my curiosity. If you are still curious you can find the source code of this page here.

Thank you...