What is the best way to rotate material's images from Ruby?

Hi all !

I’m using Sketchup for woodworking and improve my workflow by developing the OpenCutList extension. An extension to generate a quite well formated part list from the model.

Recently I release a new build of OpenCutList, that integrate a feature to rotate material’s images directly from the extension itself. I need this feature to avoid to do this from an externel image editor and to permit OpenCutList users to import any wood texture and rotate it after according to the wood grain. (The best orientation is to put the grain horizontaly in picture)

To do this I inspire myself from the Material Resizer extension that embed ImageMagick to manipulate material’s images.

Even if this grows up the size of the extension (env 8Mb), it works like a charm.

But on Windows platform, it flashes a cmd window on each ImageMagick call. Do you know a best way to do this ?

Thanks for your answer and happy coding.

you don’t need ImageMagic to simply rotate an image…

you can use js/css in the html dialog to rotate and then use ruby to take a snapshot of the dialog window…

john

Interesting strategy and thanks for your answer, John.
But what do you mean by “take a snapshot” ?

with a webDialog we had/have…

**write_image** (image_path, option, top_left_x, top_left_y, bottom_right_x, bottom_right_y) ⇒ Object

it seems to be missing from htmlDialog, but you could use js to save it locally…

I’ll have a dig and see if I updated any of mine that use/d write_image

john

Ok, interesting, I discover this feature on WebDialog.
But in this case it will be difficult to keep texture image at its original size if it is bigger than dialog, no ?

I built a image compositor using a Webdialog and just before capture I bumped it’s size up to image size, did the capture then closed it…

it seemed to work fine even if larger than my screen…

john

It mays flash to the eyes of the user :slight_smile:, no ?

Else, the main problem of using JS or WebDialog, is that currently the extension is working on SU 14 with IE 9 as minimal requirement. And I think that this technic can’t be done in this configuration, no ?

all my stuff is written on a mac and ‘some’ run on windows, from memory IE 9 should cope with html 5…

john

For version 2018 and higher, I’d say the best solution would be to use an Sketchup::ImageRep instance.

You’d transpose the pixel data depending upon the angle of rotation and then set the transposed data back to the ImageRep and then set the material’s texture to the altered ImageRep.

Thank you Dan !
I saw the ImageRep feature, but in my case it needs to work for SU 2014 and higher :frowning:

Have you seen this post ?


Aerilius also wrote a ImageMagik extension for SketchUp.

… also see his TextureResizer plugin …

https://extensions.sketchup.com/sv/content/texture-resizer

Realy interesting. Thank you Dan ! But in my tries, VB script (As Aerilius did) ask for authorization to execute on my Win 7 test computer.
I will investigate …

You might use runas to run the script under the “admin” account (or an account with elevated privileges) …

runas /noprofile /user:admin "cscript.exe C:\Scripts\Test.vbs"

Does the texture data itself have to be rotated? Can’t be done by rotating the UVs when mapping the material?

Hi Tomas !

Does the texture data itself have to be rotated?

In my use case, yes. Because the default strategy of the plugin is to search the length of each part along the red axis, the width along the green axis and the thickness along the blue axis.
In the real world, length direction (even if it’s smaller than width) equals wood grain direction.

Then it would be preferable that the material represents this “strategy”. And if the wood grain representation in the texture image is horizontal, it is correctly displayed along the red axis.

And as the material could be applyed on instance, as on faces it would be easier to have directly the correct orientation. In the goal to reduce the user operations count to have the best result.

I see. That makes sense.

By the way, I see that you can use ImageMagic as a library in many languages:

You could use a C dll library (ImageMagick – MagickWand, C API) and then use Fiddle to interface from Ruby. That will avoid the command line dialog and WScript.
Module: Fiddle (Ruby 2.5.3)

You could also look at other C image libraries - like this small header only lib:

this is meant to work in IE9…

you will need your own image file and a webdialog to test write_image

john

<!DOCTYPE html>
<html>
<body>
<button id="button" value="click here!">Click Here!</button>
<div id="parentdiv">
<img id="image"
src="file:///Users/johns_iMac/Documents/forum/4-3_9mm.png" />
</div>
<style>
#parentdiv {width:820px;height:100px;}
#parentdiv.rotate90,#container.rotate270 {width:100px;height:820px}
#image {
transform-origin: top left; /* IE 10+, Firefox, etc. */
-webkit-transform-origin: top left; /* Chrome */
-ms-transform-origin: top left; /* IE 9 */
}
#parentdiv.rotate90 #image {
transform: rotate(90deg) translateY(-100%);
-webkit-transform: rotate(90deg) translateY(-100%);
-ms-transform: rotate(90deg) translateY(-100%);
}
#parentdiv.rotate180 #image {
transform: rotate(180deg) translate(-100%,-100%);
-webkit-transform: rotate(180deg) translate(-100%,-100%);
-ms-transform: rotate(180deg) translateX(-100%,-100%);
 }
#parentdiv.rotate270 #image {
transform: rotate(270deg) translateX(-100%);
-webkit-transform: rotate(270deg) translateX(-100%);
-ms-transform: rotate(270deg) translateX(-100%);
}
</style>
<script>
var angle = 0, img = document.getElementById('parentdiv');
document.getElementById('button').onclick = function() {
angle = (angle+90)%360;
img.className = "rotate"+angle;
}
</script>

</body>
</html>

Thanks for this snippet @john_drivenupthewall ! I will take a look, but the bad thing is that HtmlDialog doesn’t have this feature. And OpenCutList uses HtmlDialog if the user run on SU 2017 and upper.

Nice tip @tt_su ! Thank you very much !