I’ve attempted to nail down what causes a seam to appear when engraving. I don’t have access to how Glowforge generates its toolpath, so this is mostly just a guess. Also, this information will only interest you if you care about the nitty gritty details of how images are represented and displayed.
My guess is it comes down to how the pixels of the tiles are interpolated and, specifically, how Glowforge is performing that interpolation. SVG is a spec and many edge cases come down to how they are implemented. I suspect this is one of those edge cases.
In my initial implementation (before I posted), I embedded the images into the SVG without an image-rendering property. When no image-rendering property is specified on an image tag in SVG, it defaults to optimizeQuality. When in this mode and sampling an image, the spec says, “The user agent shall employ a resampling algorithm at least as good as bilinear resampling.”. Bilinear resampling will combine neighboring pixels based on the distance to each one. So in the center of a specific pixel it will be that pixel’s color, but as you move continuously over to the center of one of it’s neighbors it will transition smoothly to that other color.
In this application, where we’re splitting up the image, we lose the ability to perform this continuous interpolation because each tile is now a separate image. Instead of interpolating between neighboring pixels, I wanted any sample within a pixel to be that pixels color, which is referred to as “nearest neighbor resampling”. This would prevent pixels at the edge of each tile from interpolating to white as seen in this image:
So, in the version of the application that I released, I specify the image-rendering property to be optimizeSpeed. Unfortunately, the SVG spec isn’t very specific about how this setting should be handled (and there isn’t a more specific option as far as I know). Under optimizeSpeed the spec reads:
“Indicates that the user agent shall emphasize rendering speed over quality. The user agent should use a resampling algorithm which achieves the goal of fast rendering, with the requirement that the resampling algorithm shall be at least as good as nearest neighbor resampling. If performance goals can be achieved with higher quality algorithms, then the user agent should use the higher quality algorithms instead of nearest neighbor resampling.” This suggests that nearest neighbor sampling could be used, but also says a “higher quality” algorithm could be used. Unfortunately, any “higher quality” algorithm in this case will give us undesired artifacts. This seems to be what is happening here. Glowforge is likely preferring a higher quality algorithm which introduces a seam into our tiles. Again, this is just a guess.
One option to avoid this specific issue in SVG is to use patterns. The original image could be embedded in a single pattern and rect tags could be used to reference different portions of that pattern. This would avoid having seams where the interpolation implementation introduces artifacts, but unfortunately, it looks like the Glowforge app doesn’t support patterns (I tried!).