Layers with distort perspective

Mar 24, 2014 at 8:27 PM
Hi,
I'm trying to place one image over anther image with a perceptive to the second image. I've tried 100 different things, but I'm facing 2 problems.
First problem is that the canvas of the overlay image gets crops, and the second problem is the perspective.

So here are my images:
Background: Image
Overlay: Image
This is what I want to do (made in photoshop): Image

Here are some code I tried:
using (var images = new MagickImageCollection())
            {
                var first = new MagickImage(context.Server.MapPath("~/files/house.jpg"));
                var second = new MagickImage(context.Server.MapPath("~/files/monkey.jpg"));

                double[] args =
                {
                    186,93, 185,270, 298,220, 293,133,  
                };
                second.Distort(DistortMethod.Perspective, args);
                
                images.Add(first);
                images.Add(second);
                using (var result = images.Merge())
                {
                    result.Write(context.Server.MapPath("~/files/house_with_paint.jpg"));
                }
            }
Can someone guide in what to do?
Ps, I'm fairly new to ImageMagick, and I all ready read Layering and Distorting on imagemagick.org

Thank you!
Coordinator
Mar 25, 2014 at 12:16 PM
Edited Mar 25, 2014 at 12:47 PM
I got really close with the code below. You only have to fine-tune the distortion values and the position.

I used the following example: http://www.imagemagick.org/Usage/distorts/#affine_examples
// Magick.NET understands the ~ prefix.
var first = new MagickImage(@"~\files\house.jpg");
var second = new MagickImage(@"~\files\monkey.jpg");

double[] args =
{
  // I just entered a bunch of numbers till I got close to what you want.
  0,0, 0,0,  0,120, 0,98,  200,0, 65,-50
};

second.HasAlpha = true; // -alpha set
second.VirtualPixelMethod = VirtualPixelMethod.Transparent; // -virtual-pixel transparent
second.Distort(DistortMethod.Affine, args);

// Crop part of the image so it won't overflow 'first'
int x = 105;
second.Crop(first.Width - x, second.Height, Gravity.West);
  
// Position the second image
second.Page = new MagickGeometry(x, 55, 0, 0);

using (var images = new MagickImageCollection())
{
  images.Add(first);
  images.Add(second);
  using (var result = images.Merge())
  {
    result.Write(@"~\files\house_with_paint.jpg");
  }
}
Mar 25, 2014 at 12:31 PM
wow! This is really nice!

These numbers: 186,93, 185,270, 298,220, 293,133, are actually x-y for each point of the image.
Do you know if its possible to set only x-y for each corner of the image, instead of first do the perspective, and then set position with Page?

And thank you so much for this script! It helped a lot. Gonna buy something of that wishlist.
Coordinator
Mar 25, 2014 at 12:48 PM
I am not sure if that is possible but that would make it much easier for you. I will have to look into this when I get home from work.
Mar 25, 2014 at 5:13 PM
Thank you so much!
It could be really really nice if you could help out with this.
Coordinator
Mar 25, 2014 at 8:05 PM
It took me a while but I think I have a solution for you:
// Magick.NET understands the ~ prefix.
var first = new MagickImage(@"~\files\house.jpg");
var second = new MagickImage(@"~\files\monkey.jpg");

double[] args =
{
  // Move 0x0 to 105x54
  0,0, 105,54,
  // Move 0x120 to 105x152
  0,second.Height, 105,152,
  // Move 180x0 to 163x76
  second.Width,0, 163,76,
  // Move 180x120 to 163x122
  second.Width,second.Height, 163,122
};

// Extend the second image if it does not fit in the first image.
if (second.Height < first.Height || second.Width < first.Width)
{
  second.BackgroundColor = MagickColor.Transparent;
  second.Extent(first.Width, first.Height);
}

// Perform the distortion.
second.HasAlpha = true;
second.VirtualPixelMethod = VirtualPixelMethod.Transparent;
second.Distort(DistortMethod.Perspective, args);

// Draw second image on top of first image.
first.Composite(second, Gravity.Northwest, CompositeOperator.SrcOver);
first.Write(@"~\files\house_with_paint.jpg");
Mar 25, 2014 at 8:57 PM
Thank you so much man!
2 books from your gift list is on its way :)
Coordinator
Mar 25, 2014 at 9:46 PM
Thank you very much. I send you a message through Codeplex, can you please reply the e-mail?
Mar 28, 2014 at 4:15 PM
Hi,

Can we do the same thing with a script ?
// Magick.NET understands the ~ prefix.
var first = new MagickImage(@"~\files\house.jpg");
var second = new MagickImage(@"~\files\monkey.jpg");

double[] args =
{
  // Move 0x0 to 105x54
  0,0, 105,54,
  // Move 0x120 to 105x152
  0,second.Height, 105,152,
  // Move 180x0 to 163x76
  second.Width,0, 163,76,
  // Move 180x120 to 163x122
  second.Width,second.Height, 163,122
};

// Extend the second image if it does not fit in the first image.
if (second.Height < first.Height || second.Width < first.Width)
{
  second.BackgroundColor = MagickColor.Transparent;
  second.Extent(first.Width, first.Height);
}

// Perform the distortion.
second.HasAlpha = true;
second.VirtualPixelMethod = VirtualPixelMethod.Transparent;
second.Distort(DistortMethod.Perspective, args);

// Draw second image on top of first image.
first.Composite(second, Gravity.Northwest, CompositeOperator.SrcOver);
first.Write(@"~\files\house_with_paint.jpg");
Coordinator
Mar 28, 2014 at 9:45 PM
No you can't. MagickScript does not support if statements. I might add this in the future. And the .Distort method is also not supported at the moment.
Mar 31, 2014 at 8:05 AM
Can you add Distort method please ?

Best regards
Coordinator
Apr 1, 2014 at 2:27 PM
This discussion has been copied to a work item. Click here to go to the work item and continue the discussion.