This post was actually inspired by a question in my Basecamp presentation: Could we use images to create or modify geometry in SketchUp? As it turns out, this is actually quite easy since SketchUp version 2018.
This year’s version of SketchUp includes a new class in Ruby, the ImageRep. Contrary to the regular Image class (which you can use to work with images as entities in SketchUp), the ImageRep class goes further and allows you to look at images on a pixel by pixel basis. This is basically what we need to be able to read pixel color values and then use those to create or modify geometry.
As you can see in the code snippet below, this is reasonably straightforward once one figures out the basic geometric behavior. The code even stretches the image by the (x and y) dimensions of the selected geometry.
One part that needed to be resolved was that color information in an image contains red, green, and blue data, which is not very useful here since we only need a single scaling factor. Therefore, my code includes a small routine to convert those to grayscale at values from 0.0 (white) to 1.0 (black).
You can experiment with this code using any kind of image and a bunch of “scalable” component instances (e.g. boxes) in SketchUp, similar to what we did for the beautiful functions exercise. A SketchUp model is linked below as a starting point. Note, however, that images that have a higher contrast work better here, otherwise the result remains quite flat (literally!).
Here’s an interactive version that uses my portrait image:
The code snippet below applies the image data as a scaling (in z) to objects. If you would rather like to move things around, then you need to replace that with a translation. The line below illustrates how that could look. There are two changes in this version, however. One is that I am inverting the effect simply by including
( 1 - scale ). The other is that I did not want fraction values (between zero and one) for the scale but rather only zeros and ones (either ignoring or fully moving the objects). That is done by rounding the scale with
t = Geom::Transformation.translation [ 0, 0, ( 1 - scale.round ) * 2 ]
Here is an example for this approach that you may recognize…