How can I make an on-the-fly diagonal crop?

Questions and postings pertaining to the usage of ImageMagick regardless of the interface. This includes the command-line utilities, as well as the C and C++ APIs. Usage questions are like "How do I use ImageMagick to create drop shadows?".
markr

How can I make an on-the-fly diagonal crop?

Post by markr »

Does anyone know how I can make a dynamic, on-the-fly diagonal crop (or chop) of an image? The image is a perfect square and the crop would be a perfect 45 degree angle.

(sorry if this is an easy question, but I searched and haven't been able to find the answer).

Any help is appreciated.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: How can I make an on-the-fly diagonal crop?

Post by fmw42 »

You cannot just have a diagonal line image! You have to have it filled out with some kind of padding (typically black or white) to a rectangular region. You may be able to extract the diagonal line data and format it into a string of text or into a horizontal or vertical image. Please clarify what you are really trying to do.
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: How can I make an on-the-fly diagonal crop?

Post by anthony »

You would need to mask the image to generate a non-rectangular crop.

That is you want masking, not cropping.

See IM Examples, Alpha Composition
http://www.imagemagick.org/Usage/compose/
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
markr

Re: How can I make an on-the-fly diagonal crop?

Post by markr »

Sorry for not being specific. I'm creating a picture framing engine, and I need to be able to take the images of the sides of a picture frame, do a straight rectangular crop for the sides (based on the size of the art print), and then dynamically generate the corners of the frames, using what I thought would be diagonal crops from the "discarded" part of the rectangular crop, which would resemble the mitered edges of an actual picture frame (if that makes sense).

I would have to do this in order to have the wood grain lines (for wood frames) or patterns (for patterned frames) line up correctly.

Any thoughts?
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: How can I make an on-the-fly diagonal crop?

Post by fmw42 »

still not quite sure what you want to crop, I think it is just the corner of the frame, but perhaps not.


FYI, see my simple script, picframe at http://www.fmwconcepts.com/imagemagick/index.html or Anthony's much more advanced technique at http://www.imagemagick.org/Usage/thumbnails/#frame_edge. He shows a way you can take the straight section and rotate and overlap it with itself to make the corners.
markr

Re: How can I make an on-the-fly diagonal crop?

Post by markr »

Fred, your's and Anthony's framing scripts look great, but I'm too far down the path of using the actual frame side images in my framing engine.

Really what I'm trying to do is to crop (or overlay) the straight sections at 45 degree angles (just like it's done when an art print is actually framed).

The reason I want to crop (or overlay) them at 45 degree angles (and not rotate them) is to have the 45 degree "corners" line up with the wood grain (or pattern) of the straight sections that they came from.

Do you think it's possible to do this?
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: How can I make an on-the-fly diagonal crop?

Post by fmw42 »

I think you will need to show me (us) an example as I am still not quite sure what you need. My only thought is to crop, rotate and then crop again or possibly use -virtual-pixels to extend/unfold the image so you have more to work with. An example would help understand what you want to do. Unfortunately, I have no experience with actual physical framing to really understand so far. Sorry for being so dense about this.

Perhaps all you need to do is crop a square section of the top end of the right-side frame, mask half at a 45 degree angle with the one half transparent. Then do the same with the right end of the top-side frame, then composite the two squares together so the transparent parts of one overlay the opaque parts of the other. That forms your corner. Is that what you want?

see -draw with matte floodfill http://www.imagemagick.org/script/magic ... aphics.php to fill a triangular polygon with transparency. The triangle would be 3 corners of the square. also see http://www.imagemagick.org/Usage/color/#floodfill_draw
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: How can I make an on-the-fly diagonal crop?

Post by anthony »

The script fred and I use only use rotate for 90 degree rotates. The 45 degree angle is generated using masking methods. No rotates involved.

My technique is to use the output of the -frame operator to generate the 45 degree cut masks. The masks are then filled using the framing tile pieces. Another technique is to draw the mask for for 45 degree cut.

Fred's script uses pre-prepared frames that already contain the 45 degree join. These are stretched or extended out so are to be sized to fit the image.

Perhaps a SMALL example of what you are after would help us help you.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
markr

Re: How can I make an on-the-fly diagonal crop?

Post by markr »

Fred / Anthony: first of all, thanks for taking the time helping me...

And forgive me for being dense, but I'm not sure what you want in terms of an example; let me know what you're looking for and I'll do my best to provide it.

As one last chance at an explanation, I'm trying to take two rectangular images and connect them at a 45 degree angle (just like the 45 degree miter cuts an actual framer does on two pieces of a frame). So, I just need to "cut out" (or mask? or crop?) the triangular piece from each rectangular piece to have them connect at a 45 degree angle.

Here are the exact details of what I'm trying to do: I have actual images of frames cut into 8 pieces: the four corners and the four sides. My framing engine currently uses all 8 frame images in a three row, three column HTML table (with the art print going into the middle cell). The problem with this is that the frame side images are either stretched or compacted, based on the size of the art print.

I'm now attempting to only use the actual top left corner frame image, discard my other 3 actual corner images, and create the other three corner images on-the-fly (using the actual frame side images).

Using ImageMagick's crop function, I should be able to crop the actual frame side images at 90 degree angles (based on the size of the art print I'm framing), so that the frame sides don't look stretched or compacted. But for the 3 corners that I need to dynamically generate from the side images, I need them cut/cropped/masked at 45 degree angles (which is where I need the assistance).

Does that explanation help?
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: How can I make an on-the-fly diagonal crop?

Post by fmw42 »

provide your side images and we can try to make the corners and show you how. post links to your side images (at least two, for example, top and right sides, and we can make the top-right corner)
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: How can I make an on-the-fly diagonal crop?

Post by anthony »

markr wrote:Here are the exact details of what I'm trying to do: I have actual images of frames cut into 8 pieces: the four corners and the four sides. My framing engine currently uses all 8 frame images in a three row, three column HTML table (with the art print going into the middle cell). The problem with this is that the frame side images are either stretched or compacted, based on the size of the art print.
Oh your mean using tables to generate automatically resized framework around the image.
A bit like this Resizing scroll...
http://www.cit.gu.edu.au/~anthony/wwwla ... rt/scroll/
or the other examples in...
http://www.cit.gu.edu.au/~anthony/wwwla ... _text.html

However these HTML table examples tile the edge pieces in the background of that table cell. The actual foreground contents is just a single pixel space image! That is this method 'tiles', I do not ask the HTTP client to resize the images to exactly the width and height needed!
I'm now attempting to only use the actual top left corner frame image, discard my other 3 actual corner images, and create the other three corner images on-the-fly (using the actual frame side images).
That should be no problem. and I generate miter joins like this in the framing examples pointed out earlier.. 45 degree corner joints.

Give use link to the edging images and I'll should you how to make a corner piece using masked composition.
Using ImageMagick's crop function, I should be able to crop the actual frame side images at 90 degree angles (based on the size of the art print I'm framing), so that the frame sides don't look stretched or compacted.
Yes. If you are wanting to set the correctly sided image for the table. If it is tilable, a smaller image is better as it is less bandwidth to send.
But for the 3 corners that I need to dynamically generate from the side images, I need them cut/cropped/masked at 45 degree angles (which is where I need the assistance).
3 corners? Their are always 4 corners ;-)

If you are going to send ALL the pixels of the frame, why not just merge all the pieces into a single image for transmission. that way you get better compression and only one file and network connection for all 9 images (8 frames and the central image).
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
markr

Re: How can I make an on-the-fly diagonal crop?

Post by markr »

Fred / Anthony,

The top frame image is at:

http://www8.picfront.org/picture/q85BBt ... mg/top.jpg

and the right frame image is at:

http://www8.picfront.org/picture/R2EqnL ... /right.jpg


I appreciate you using these images to let me know how to create the top right corner...
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: How can I make an on-the-fly diagonal crop?

Post by fmw42 »

Note: Anthony's whole picture framing approach is much simpler and easier as you don't have to do any special separate processing for the corners. They come automatically by his method of merging the side pieces with the frame technique.

However, if you must, here is one way to do it. I have kept the steps separate to show the images:


convert frameright.jpg -gravity east -crop 145x145+0+0 +repage framerightcrop.png
Image

convert frametop.jpg -gravity north -crop 145x145+0+0 +repage frametopcrop.png
Image

convert -size 145x145 xc:black -fill white -draw "polygon 0,0 0,145 145,0" framemask.png
Image

convert frametopcrop.png framemask.png -alpha off -compose copy_opacity -composite frametopcropm.png
Image

convert -respect-parenthesis framerightcrop.png \( framemask.png -negate \) \
-alpha off -compose copy_opacity -composite framerightcropm.png
Image

convert frametopcropm.png framerightcropm.png -compose over -composite frametopright.jpg
Image

Putting it in one command line (just for the top right corner), it becomes:

convert -respect-parenthesis \
\( frametop.jpg -gravity north -crop 145x145+0+0 +repage -write frame1.png \) \
\( frameright.jpg -gravity east -crop 145x145+0+0 +repage -write frame2.png \) \
\( -size 145x145 xc:black -fill white -draw "polygon 0,0 0,145 145,0" -write frame3.png \) \
\( -clone 2 -negate -write frame4.png \) \
\( -clone 0 -clone 2 -alpha off -compose copy_opacity -composite -write frame5.png \) \
\( -clone 1 -clone 3 -alpha off -compose copy_opacity -composite -write frame6.png \) \
-delete 0-3 -compose over -composite frametopright.jpg
Last edited by fmw42 on 2009-07-04T11:30:20-07:00, edited 2 times in total.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: How can I make an on-the-fly diagonal crop?

Post by fmw42 »

This is another way to do it, perhaps more like the diagonal crop you want, but it leaves a diagonal artifact after the two pieces are merged.. Note, this is corrected further below.

convert frametop.jpg -gravity north -crop 145x145+0+0 +repage \
-draw "polygon 145,145 0,145 145,0 fill none matte 135,135 floodfill" \
frametopdiagcrop2.png
Image

convert frameright.jpg -gravity north -crop 145x145+0+0 +repage \
-draw "polygon 0,0 0,145 145,0 fill none matte 10,10 floodfill" \
framerightdiagcrop2.png
Image

convert frametopdiagcrop2.png framerightdiagcrop2.png -compose over -composite \
frametopright2.jpg
Image


So to fix this, we have to use a new technique that Anthony developed to spread/blur the image a bit just outside the transparent mask. So the modified technique becomes:

convert frametop.jpg -gravity north -crop 145x145+0+0 +repage \
-draw "polygon 145,145 0,145 145,0 fill none matte 135,135 floodfill" \
\( +clone -channel RGBA -blur 1x65000 \) \
-compose DstOver -composite frametopdiagcrop3.png
Image

convert frameright.jpg -gravity north -crop 145x145+0+0 +repage \
-draw "polygon 0,0 0,145 145,0 fill none matte 10,10 floodfill" \
\( +clone -channel RGBA -blur 1x65000 \) \
-compose DstOver -composite framerightdiagcrop3.png
Image

composite -blend 50% frametopdiagcrop3.png framerightdiagcrop3.png \
frametopright3.jpg
Image
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: How can I make an on-the-fly diagonal crop?

Post by anthony »

Your pieces will not join very well in any HTML table as they have a lot of repeating detail.
As such the only good way of doing this it to generate the images at the specific size needed
for the table.

Fully framing the image (see the previously given links) and either using the image fully framed, or dividing the images for the table again, is thus the best method of ensuring all the pieces match up correctly.

Also note that the frame probably needs some color work as they do not tile very well.

The detail on the right.jpg image will match up top to bottom, but the top is a LOT brighter than the bottom of the piece. To see this look at the output of this command

Code: Select all

   convert right.jpg right.jpg -append show:
The top piece detail does not match up at all.



On aligning masked images...

The best idea is to use the same mask (negated) for BOTH peieces, rather than attempting to draw the two masks separately. Otherwise you have the two masks overlap, OR leave a gap, exactly as you have seen.

correct methods of mask joining.. Other methods will work for a pure boolean mask (as produced by -frame, or -draw with the +antialias setting), but is likely to fail if the mask contains any grayscale anti-aliasing pixels, as the transparency will be WRONG!

Over compose with TWO masked images for example is actually definatally WRONG, as an over of two semi-transparent pixels will never produce full opaqicy. Plus composite is the correct why.

For an example of this see...
http://www.imagemagick.org/Usage/compose/#dstout
where two masked images (dst_in and dst_out), are re-joined together correctly.

For more on the difference between over and plus see Blend (plus) vs Dissolve (over) http://www.imagemagick.org/Usage/compos ... d_dissolve
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
Post Reply