Turn an image into a 3D landscape. Each pixel is turned into a line with it's height proportional to it's grayscale value.
The ImagickPixelIterator class Example #2: 3D Landscape
http://eclecticdjs.com/mike/tutorials/p ... dscape.php
3D Landscape Effect
3D Landscape Effect
DJ Mike's Tutorials: PHP
ImageMagick Functions
http://eclecticdjs.com/mike/tutorials/p ... /index.php
ImageMagick Functions
http://eclecticdjs.com/mike/tutorials/p ... /index.php
- fmw42
- Posts: 25562
- Joined: 2007-07-02T17:14:51-07:00
- Authentication code: 1152
- Location: Sunnyvale, California, USA
Re: 3D Landscape Effect
Nice to be able to do something like that in IM.
For reference, see my publications on my web site at http://www.fmwconcepts.com/fmw/fmw.html
and particular my survey paper F.M. Weinhaus and V. Devarajan, Texture Mapping 3D Models of Real-World Scenes, ACM Computing Surveys, Vol. 29, No. 4, 325-365, December 1997.
For reference, see my publications on my web site at http://www.fmwconcepts.com/fmw/fmw.html
and particular my survey paper F.M. Weinhaus and V. Devarajan, Texture Mapping 3D Models of Real-World Scenes, ACM Computing Surveys, Vol. 29, No. 4, 325-365, December 1997.
-
- Posts: 1015
- Joined: 2005-03-21T21:16:57-07:00
Re: 3D Landscape Effect
Mike,
I think the reason that this script uses so much ram and takes a long time is because you don't need to use pixel iterators at all because you aren't modifying the source image like you do in the ripple example. In fact, you don't actually use the iterators other than to find which row you are currently working on and there's a much easier way to do that by using a for loop.
Pete
I think the reason that this script uses so much ram and takes a long time is because you don't need to use pixel iterators at all because you aren't modifying the source image like you do in the ripple example. In fact, you don't actually use the iterators other than to find which row you are currently working on and there's a much easier way to do that by using a for loop.
Pete
Sorry, my ISP shutdown all personal webspace so my MagickWand Examples in C is offline.
See my message in this topic for a link to a zip of all the files.
See my message in this topic for a link to a zip of all the files.
Re: 3D Landscape Effect
Thanks. As obvious as that is now I missed it until you pointed it out. I tried running the avatar example again today and it ran for 8 minutes then gave me a 500 error. I changed it to the nested while loops that are posted below and it "only" took 1:26 the first time and 0:28 the second run. Now that I see that it isn't a good example of pixel iteration I'll have to think of somewhere else to put it.el_supremo wrote:Mike,
I think the reason that this script uses so much ram and takes a long time is because you don't need to use pixel iterators at all because you aren't modifying the source image like you do in the ripple example. In fact, you don't actually use the iterators other than to find which row you are currently working on and there's a much easier way to do that by using a for loop.
Pete
Code: Select all
<?php
//set php script timeout, 0 to disable
set_time_limit(0);
# starting image
$url = "http://eclecticdjs.com/mike/images/avatar.jpg";
$file = "3d_avatar.jpg"; # name of finished image
# Read image as blob
$blob = file_get_contents("$url");
# make new imagick object from blob
$image = new imagick();
$image->readImageBlob("$blob");
# scale it down
$image->scaleimage(150, 0);
$image->shearImage("transparent", 45,0);
# scale it to make it look like it is laying down
$w = $image->getimagewidth();
$h = $image->getimageheight();
$image->scaleimage($w, $h/2);
# Get image stats
$w = $image->getimagewidth();
$h = $image->getimageheight();
$format = $image->getimageformat();
#### Make a pallet to draw on
$pallete = new Imagick;
$pallete->newimage($w,$h*2, "blue");
$p_w = $image->getimagewidth();
$p_h = $image->getimageheight();
$dif = $p_h-$h;
$pallete->setimageformat("$format");
####
$row = new ImagickPixelIterator($image);
$x = 1;
$y = 1;
#############################
# loop through all points
# while ( $row->getNextIteratorRow() )
while ( $y <= $h )
#############################
{
while ( $x <= $w)
{
# get (r,g,b) and grey value
$point = $image->getImagePixelColor( $x, $y );
$color = $point->getColor();
$r = $color[r];
$g = $color[g];
$b = $color[b];
# Calculate grayscale
$grey = ($r+$g+$b)/25;
$grey =(int)$grey;
# Make line with height proportional to grayscale
$line = new ImagickDraw;
$line->setfillcolor("rgb($r,$g,$b)");
$line->setstrokecolor("rgb($r,$g,$b)");
#$line->setstrokewidth(1);
$line_height = $y-$grey;
$offset = 75;
#############################
#$y = $row->getIteratorRow();
#$y++;
#############################
$start_y = $y+$offset;
$end_y = $y-$grey+$offset;
$line->line( $x, $start_y, $x, $end_y);
# draw the line
$pallete->drawimage($line);
# Free up memory
$point->destroy();
$line->destroy();
unset($color);
$x++;
}
$x = 1;
$y++;
}
$pallete->scaleimage(250, 150);
# write pallet
$pallete->writeimage( "$file");
#header("content-type:image/$format");
header("Location:$file");echo $pallete;
exit;
?>
DJ Mike's Tutorials: PHP
ImageMagick Functions
http://eclecticdjs.com/mike/tutorials/p ... /index.php
ImageMagick Functions
http://eclecticdjs.com/mike/tutorials/p ... /index.php
- fmw42
- Posts: 25562
- Joined: 2007-07-02T17:14:51-07:00
- Authentication code: 1152
- Location: Sunnyvale, California, USA
Re: 3D Landscape Effect
In general, I think for loops are faster than while loops. At least that has been my experience on my Mac when scripting in bash.
-
- Posts: 1015
- Joined: 2005-03-21T21:16:57-07:00
Re: 3D Landscape Effect
Hi Mike,
A few comments on your new code:
1. You still instantiate an ImagickPixelIterator but don't use it - probably forgot to comment it out
2. The while loops would be easier to read as for loops and when indexing
into an image with ImageMagick the indices start at zero so either use
OR use
and remove $x++; and $x=1;$y++; from the bottom of the loops.
3. I converted your example to C and I'm using it as a MagickWand Example in C (see my sig).
While doing this I found that it is about 25% faster to create, draw and destroy
the "line" drawingwand outside the inner loop. Your code is similar to this:
It will execute faster arranged like this:
I also found that drawing the image from top to bottom, while it is easy to do, requires drawing a lot of lines which will only be overwritten by a later line that is in "front" of them and so covers them up. I modified my C version so that it starts at the bottom of the image and goes up each column, keeping track of the length of the most recently drawn line and only drawing a new one if it is longer. This can speed up the process by a factor of four or more. If you're interested, have a look at my code at http://members.shaw.ca/el.supremo/Magic ... ape_3d.htm
Pete
A few comments on your new code:
1. You still instantiate an ImagickPixelIterator but don't use it - probably forgot to comment it out
Code: Select all
$row = new ImagickPixelIterator($image);
into an image with ImageMagick the indices start at zero so either use
Code: Select all
$x = 0;
$y = 0;
while ( $y < $h )
{
while ( $x < $w)
OR use
Code: Select all
for($y=0;$y<$h;$y++)
{
for($x=0;$x<$w;$x++)
3. I converted your example to C and I'm using it as a MagickWand Example in C (see my sig).
While doing this I found that it is about 25% faster to create, draw and destroy
the "line" drawingwand outside the inner loop. Your code is similar to this:
Code: Select all
for($y=0;$y<$h;$y++)
{
for($x=0;$x<$w;$x++)
{
.
.
.
$line = new ImagickDraw;
.
.
$line->line( $x, $start_y, $x, $end_y);
# draw the line
$pallete->drawimage($line);
$line->destroy();
}
It will execute faster arranged like this:
Code: Select all
for($y=0;$y<$h;$y++)
{
$line = new ImagickDraw;
for($x=0;$x<$w;$x++)
{
.
.
$line->line( $x, $start_y, $x, $end_y);
}
# draw the line
$pallete->drawimage($line);
$line->destroy();
Pete
Sorry, my ISP shutdown all personal webspace so my MagickWand Examples in C is offline.
See my message in this topic for a link to a zip of all the files.
See my message in this topic for a link to a zip of all the files.
Re: 3D Landscape Effect
Thanks for the tips. I don't know C but I can follow almost all of it and I copied to study later.
DJ Mike's Tutorials: PHP
ImageMagick Functions
http://eclecticdjs.com/mike/tutorials/p ... /index.php
ImageMagick Functions
http://eclecticdjs.com/mike/tutorials/p ... /index.php
Re: 3D Landscape Effect
I have not modified the scripts yet but I thought this other example was nice. I knew that my multi-color shirt wouldn't make a good 3D effect but the illusion of my hand standing out of the rest of the image is pretty convening. I changed the $gray divisor to 100 to make the hand less exaggerated and more lifelike.
Before
http://eclecticdjs.com/mike/tutorials/p ... possum.jpg
After
http://eclecticdjs.com/mike/tutorials/p ... possum.jpg
Before
http://eclecticdjs.com/mike/tutorials/p ... possum.jpg
After
http://eclecticdjs.com/mike/tutorials/p ... possum.jpg
DJ Mike's Tutorials: PHP
ImageMagick Functions
http://eclecticdjs.com/mike/tutorials/p ... /index.php
ImageMagick Functions
http://eclecticdjs.com/mike/tutorials/p ... /index.php