Page 1 of 3

Canvas wrap transformation

Posted: 2012-06-17T08:18:56-07:00
by lenscape
I'm trying to figure out how to use ImageMagick to transform an image so it looks like it's a canvas wrap, seen from off-centre, slightly from one side.

This is a pretty good example of what the finished image might look like: Image.

So I would guess there are probably several steps to the transformation:

1. Trim off about 5% of the image on all four sides and throw them away, except for the left (or right) edge.
2. Transform the left (or right) sliver to make a side.
3. Transform the main image so the right (or left) edge looks further away.
4. Join the sliver and main image to give a boxy look.
5. Draw a thin white 60%-80% translucent line down the edge to give the wrapped corner a shine.

I don't need the shadow in this image as the idea would be to put the finished transformation on a room scene to appear on the wall. The virtual pixels background would be transparent.

I assume I need "-distort perspective" but I'm not getting very far with it at all so I obviously don't get something.

Thanks for any help with this.

Cheers.

Dale

Re: Canvas wrap transformation

Posted: 2012-06-17T09:22:03-07:00
by Bonzo
You do not say how you are running the code which would be helpful and post what you have and we can help.

I would resize the image during upload to speed up the next part of the process then:

1/ Crop out the center part and do a perspective distort.
2/ Crop the left piece and do another perspective distort.
3/ Join the two parts - I am not sure how to get the gray line to highlight the vertical corner.

Re: Canvas wrap transformation

Posted: 2012-06-17T10:59:34-07:00
by fmw42

Re: Canvas wrap transformation

Posted: 2012-06-17T18:08:30-07:00
by anthony
You may need to generate a 'perfect grey' version of the final image, so you can add the appropriate shades and highlights. This will be applied against the distorted image, to set the 'fluff' that makes it all work.

See the various 'Badge' examples in thumbnails, to see what I mean
http://www.imagemagick.org/Usage/thumbnails/
Especially...
http://www.imagemagick.org/Usage/thumbn ... e_lighting

This is especially important for the 'edge highlights' which in the example shown, would otherwise not be a simple effect. But also for shadow effects, and possibly some Vignetation effects that may be desirable to de-emphasize the corners.
http://www.imagemagick.org/Usage/transform/#vignette

The effect can be natural part of the photo taking, but is typically not strong enough.
http://www.imagemagick.org/Usage/photos/#vignettation

A full example (and pointer to a long discussion) of this type of things was done for 'DVD boxes'
http://www.imagemagick.org/Usage/distorts/#box3d

Re: Canvas wrap transformation

Posted: 2012-06-29T18:58:38-07:00
by cjmi
Lenscape, if you get this working, would you be willing to share the code?

I wouldn't use it exactly, just as a reference, actually. But, I need to do something similar.

Re: Canvas wrap transformation

Posted: 2012-06-30T00:20:06-07:00
by Bonzo
This is some code I wrote; I have added some "highlights" to the corners but an not 100% happy with the way they look.

Code: Select all

<?php

// Input image
$image = 'result2.jpg';

// Resize to a png to stop quality loss
exec("convert $image -thumbnail 500x500 temp.png");

// Get the size of the original image
$size = getimagesize('temp.png');
// The canvas frame edge
$edge = $size[0]*.06;
// New central portion width
$width = $size[0] - ( $edge * 2 );
// New central portion height
$height = $size[1] - ( $edge * 2 );
// Reduction of edge width
$shrink = round(( $edge * 0.6 ), 2);
// Angle of the edge
$angle = 30;
// Change in edge height
// Convert angle to radian > angle in degrees * Pi / 180 
$radian = ( $angle * Pi() ) / 180;
$alpha = round((abs(tan($radian)) * $shrink), 2);
// Edge short side
$short_side = round( ($height - $alpha ), 2);
// Top long side 
$top_long = round($width + $shrink, 2);

/*
echo "
edge = $edge<br>
width = $width<br>
height = $height<br>
shrink = $shrink<br>
Angle = $angle<br>
Alpha = $alpha<br>
short side = $short_side<br>
Top long side = $top_long<br>";
*/

// Create the highlights image
$width_short = $width-1;
$width_long = $width+1;
$width_top = $width-2;
$cmd = " -size {$width}x{$height} xc:none -stroke rgba(211,211,211,0.6) -strokewidth 3 -fill none -draw \" line 0,-2 $width_short,1 \" -draw \" line $width_top,2 $width_long,$height  \"";
exec("convert $cmd highlights.miff");

// Crop for the edges
$cmd = " temp.png ( -clone 0 -crop {$width}x{$height}+{$edge}+{$edge} highlights.miff -composite -write center.miff +delete )".
" ( -clone 0 -crop {$width}x{$edge}+$edge+0 -write top.miff +delete )".
" -gravity northeast -crop {$edge}x{$height}+0+{$edge} -write right.miff +delete null: ";
exec("convert $cmd ");

// Perspective for the RHS
$cmd = " right.miff -virtual-pixel background -background none ".
" +distort Perspective \"0,0 0,0  $edge,0 $shrink,-$alpha  $edge,$height $shrink,$short_side  0,$height 0,$height\" +repage -trim";
exec("convert $cmd right_edge.miff");

// Perspective for the top
$cmd = " top.miff -virtual-pixel background -background none ".
" +distort Perspective \"0,0 $shrink,0  $width,0 $top_long,0  $width,$edge $width,$alpha  0,$edge 0,$alpha\" +repage -trim";
exec("convert $cmd top_edge.miff");

// There was a 1px gap between the RHS and main photo
$tweek = $width-1;

// Join the images
$cmd = " ( -page -1,0 top_edge.miff -page +0+$alpha center.miff -page +$tweek+0 right_edge.miff -background none -layers merge ) ".
" ( +clone -background black -shadow 95x10+15+15 ) +swap -background none -layers merge +repage ";
exec(" convert $cmd appended.png");

// Display the final image
echo "<img src=\"appended.png\">";

// Alternative style
$cmd = " appended.png -virtual-pixel background -background none ".
" +distort Perspective \"0,0 0,-40  962,0 962,0  962,602 962,602  0,602 0,562\" +repage -trim";
exec("convert $cmd test_canvas.png");

// Display the final image
echo "<img src=\"test_canvas.png\">";

// Cleanup
foreach ( glob("*.miff") as $filename ) { unlink($filename); }
?>
Image
Image

Re: Canvas wrap transformation

Posted: 2012-06-30T09:39:26-07:00
by fmw42
Nice work Bonzo!

Re: Canvas wrap transformation

Posted: 2012-06-30T12:58:12-07:00
by Bonzo
Thanks fmw42

Re: Canvas wrap transformation

Posted: 2012-07-01T16:42:43-07:00
by anthony
Bonzo, Is your example actually even using perspective?
It looks like you specific variant can be achieved using simpler Affine Distortions!

As a small criticism for improvement, The lines in the corner look very blurry. a single pixel line, of varying intensity would probably work better.

The question then becomes, how would you draw a line of variable intensity? Quite a problem in itself.
I'll start a new topic for this!

Re: Canvas wrap transformation

Posted: 2012-07-01T17:50:12-07:00
by fmw42
Bonzo, Is your example actually even using perspective?
It is using perspective for the top and right side. See the lines where he uses +distort perspective

Re: Canvas wrap transformation

Posted: 2012-07-01T19:29:22-07:00
by anthony
No I can see he used perspective distort, but are the coordinates adding perspective?
The image does not seem to be very perspective like, the first certainaly is a affine distort (via perspective distort).
Remember affine is a special sub-set of the perspective distortion.

Re: Canvas wrap transformation

Posted: 2012-07-02T00:09:24-07:00
by Bonzo
I had just left the "front" square as that was the effect I wanted and distorted the edges - I probably could have used shear for the edges.
To give it a perspective would it be better to add an extra distort at the end? I will try it out at some point.

I am not happy with the highlight lines. I made the lines 3px wide but started them off the image by 2px to make them thinner at one end. What I would like is a line that made the edges look slightly rounded which would be a gradiant?

I suppose that once the code for the calculations and my first example are worked out I could have alternate distorts at the end to use an exagerated perspective distort as per the original post.

Re: Canvas wrap transformation

Posted: 2012-07-02T11:11:56-07:00
by Bonzo
Adding a perspective distortion at the end did not look good as I have the top of the canvas print; it would need rewriting from scartch.

Image

I suppose I could change the shape of the top - narrow down the end furthest away and change the angle at the end.

Re: Canvas wrap transformation

Posted: 2012-07-02T11:27:53-07:00
by fmw42
Although I have not tested anything but square image. My 3Dbox script, at the link below, should be able to make a box of any size (not just square) and rotate it as desired. Then one can add a shadow behind it as desired external to the script. One has to pre-crop out the side pieces and center piece as desired to make a consistent box.

Re: Canvas wrap transformation

Posted: 2012-07-02T18:40:48-07:00
by anthony
Bonzo wrote:I suppose I could change the shape of the top - narrow down the end furthest away and change the angle at the end.
Remember coordinates are floating point in both Draw and Distort, but the two uses different coordinate systems (different reasons).

Distort uses Image Coordinates (0,0 is actual top-left edge of the image).
Draw also use floating point but uses Pixel Coordinates (0,0 is center of top-left pixel, not the actual edge)

The difference is just a offset of 0.5 (half a pixel), but it can be an important difference, when mixing draw and distort.

See Image Coordinates..
http://www.imagemagick.org/Usage/distor ... oordinates