Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I have a rectangular image that I can not change.

I'd like to clip the image with a bezier path so I get one that is rectangular at the top and the sides but has a curve at the bottom, preferable without using additional packages.

share|improve this question
1  
No package needed if you clip the image using an image editor in advance. As far as I know, graphicx can only clip images in a rectangular form. Therefore you need additional packages such as PSTricks to clip it in a curved form. –  xport Jun 5 '11 at 12:15
    
Using an editor in advance is not an option, unfortunatelly. Additional packages are acceptable (thou a solution without them would be preferable). –  Richard Durr Jun 5 '11 at 12:17
    
Your image in what format? eps, jpeg, png, or pdf? –  xport Jun 5 '11 at 12:24
    
can be converted during the compile-process. let us assume it is png. –  Richard Durr Jun 5 '11 at 13:10
1  
Herbert's solution that is compiled by xelatex can import png, pdf, jpg, eps. –  xport Jun 5 '11 at 13:13
add comment

5 Answers

up vote 14 down vote accepted

I don't know of a way to clip an image without using additional packages (apart from graphicx, I assume). There is a way of doing it with TikZ, which is probably better than no solution.

This is based on the answers to the question Drawing on an image with TikZ. I've written a macro that takes an image name with the accompanying \includegraphics options and a TikZ path as arguments to either display the image overlaid with a grid and the path, or to use the path to clip the image. The behaviour is toggled using \tikzset{develop clipping path=true} to switch on the grid and the path display, and \tikzset{develop clipping path=false} to perform the actual clipping once the path has been developed.

    \documentclass{article}

    \usepackage{tikz}
    \usepackage{graphicx}

    \newif\ifdeveloppath
    \tikzset{/tikz/develop clipping path/.is if=developpath,
      /tikz/develop clipping path=true}

    \newcommand{\clippicture}[2]{
      \begin{tikzpicture}
    % Include the image to determine the size and set up the relative coordinate system. Enclose the \includegraphics in \phantom{} once the clipping path has been set up
    \ifdeveloppath
      \node[anchor=south west,inner sep=0] (image) at (0,0) {\includegraphics#1};
    \else
      \node[anchor=south west,inner sep=0] (image) at (0,0) {\phantom{\includegraphics#1}};
    \fi
    \pgfresetboundingbox
    \begin{scope}[x={(image.south east)},y={(image.north west)}]
      % Draw grid while developing clipping path
      \ifdeveloppath
        \draw[help lines,xstep=.1,ystep=.1] (0,0) grid (1,1);
        \foreach \x in {0,1,...,9} { \node [anchor=north] at (\x/10,0) {0.\x}; }
        \foreach \y in {0,1,...,9} { \node [anchor=east] at (0,\y/10) {0.\y}; }
        \draw[red, ultra thick] #2 -- cycle;
      \else
        % Use the path to clip, include the image
        \path[clip] #2 -- cycle;
        \node[anchor=south west,inner sep=0pt] {\includegraphics#1};
      \fi
    \end{scope}
    \end{tikzpicture}
    }

    \begin{document}
Show the image with a grid to help in finding the coordinates for the path.

    \clippicture{[width=0.8\textwidth]{some-image}}{(0.5,0.75) -- (0.90,0.75) -- (0.90,0.5) .. controls (0.8,-0.2) and (0.65,0.2) .. (0.5,0.3)}

    \tikzset{develop clipping path=false}
Done with developing the path. Do the actual clipping.

    \clippicture{[width=0.8\textwidth]{some-image}}{(0.5,0.75) -- (0.90,0.75) -- (0.90,0.5) .. controls (0.8,-0.2) and (0.65,0.2) .. (0.5,0.3)}
    \end{document}

clipping an image with a bezier

share|improve this answer
    
Cool, thanks! :) –  Richard Durr Jun 5 '11 at 13:15
add comment

run with xelatex, then a pdf image can be clipped

\listfiles
\documentclass{article}
\usepackage{graphicx,pstricks}
\newsavebox\IBox
\begin{document}

\savebox\IBox{\includegraphics{/tmp/two.pdf}}

\begin{pspicture}(\wd\IBox,\ht\IBox)
\psclip{\pscustom[linestyle=none]{%
  \psline(0,0.2\ht\IBox)(0,\ht\IBox)(\wd\IBox,\ht\IBox)(\wd\IBox,0.3\ht\IBox)
  \psbezier(0.75\wd\IBox,0)(0.25\wd\IBox,0.5\ht\IBox)(0,0.2\ht\IBox)}}
  \rput[lb](0,0){\usebox\IBox}
\endpsclip
\end{pspicture}

\end{document}

enter image description here

share|improve this answer
    
It is a compact solution with a nice photograph. –  xport Jun 5 '11 at 13:09
    
I'll evaluate this solution, too! Thanks! :) –  Richard Durr Jun 5 '11 at 13:15
    
You can use \pst@boxg as a temporary box. –  xport Jun 22 '11 at 7:39
1  
@xport: I know, but it requires makeatletter ....\makeatother and it is defined for internal use of PSTricks –  Herbert Jun 22 '11 at 7:45
add comment

I take some ideas from Drawing on an image with Tikz but with another method and I complete the code with Jack's method for the clip image.

\documentclass{scrartcl}
\usepackage{tikz,fullpage}
\usetikzlibrary{fit,calc,spy} 

\tikzset{number/.style={fixed,fixed zerofill,precision=1}} 
\makeatletter  
\tikzset{spy style/.style={spy using outlines={magnification=8, size=4cm}}}
\newenvironment{IncludeGH}[2][\textwidth]{%
\def\GHClipImage{#2}
\begin{scope}[spy style] 
\node[anchor=south west,inner sep=0](GHimage){\includegraphics[width=#1]{#2}}; 
\begin{scope}[x={(GHimage.south east)},y={(GHimage.north west)}]}{% 
\end{scope}\end{scope}
}

\newenvironment{IncludeClipGH}[2][\textwidth]{%
\def\GHClipImage{#2}
\begin{scope}
\node[anchor=south west,inner sep=0](GHimage){\phantom{\includegraphics[width=#1]{#2}}}; 
\begin{scope}[x={(GHimage.south east)},y={(GHimage.north west)}]}{% 
\end{scope}\end{scope}
}   

\pgfkeys{GHShowDetail/.cd,
width/.code                    = \def\GH@width{#1},
height/.code                   = \def\GH@height{#1}, 
/GHShowDetail/.unknown/.code   = {\let\searchname=\pgfkeyscurrentname
                                  \pgfkeysalso{\searchname/.try=#1,
                                  /tikz/\searchname/.retry=#1}}}

\def\GHShowDetail{\pgfutil@ifnextchar[{\GH@ShowDetail}{\GH@ShowDetail[]}}
\def\GH@ShowDetail[#1] at (#2,#3)#4{
\pgfkeys{GHShowDetail/.cd,
         width   = 0.1,
         height  = 0.1}
\pgfqkeys{/GHShowDetail}{#1}
    \path (#2,#3)--++(\GH@width/2,\GH@height/2) coordinate (rightnode)
          (#2,#3)--++(-\GH@width/2,-\GH@height/2) coordinate (leftnode);
    \node [fit=(leftnode) (rightnode),
           ultra thick,draw,
           color= lightgray,
           ](#4)  {};}

\pgfkeys{GHShowPath/.cd,
/GHShowPath/.unknown/.code   = {\let\searchname=\pgfkeyscurrentname
                                  \pgfkeysalso{\searchname/.try=#1,
                                  /tikz/\searchname/.retry=#1}}}

\def\GHShowPath{\pgfutil@ifnextchar[{\GH@ShowPath}{\GH@ShowPath[]}}
\def\GH@ShowPath[#1]#2{
\pgfqkeys{/GHShowPath}{#1}
        \draw[#1] #2 -- cycle; 
}

\def\GHShowClipPath{\pgfutil@ifnextchar[{\GH@ShowClipPath}{%
                                         \GH@ShowClipPath[]}}
\def\GH@ShowClipPath[#1]#2{
\pgfqkeys{/GHShowPath}{#1}
\clip  #2 -- cycle;
\node[anchor    = south west,
      inner sep = 0](GHimage){%
      \includegraphics[width=12cm]{\GHClipImage}};
}  

\newif\ifanchor@show\anchor@showfalse
\pgfkeys{GHAnchor/.cd,
color/.code         = \def\GH@anchor@col{#1},
radius/.code        = \def\GH@anchor@rad{#1},
show/.is if         = anchor@show,
show/.default       = true}

\def\GHAnchor{\pgfutil@ifnextchar[{\GH@Anchor}{\GH@Anchor[]}} 
\def\GH@Anchor[#1] at (#2,#3)#4{%
\pgfkeys{/GHAnchor/.cd,
color  = gray,
radius = 2pt,
show   = false}  
\pgfqkeys{/GHAnchor}{#1}  
\coordinate (#4) at (#2,#3);
\ifanchor@show\fill[\GH@anchor@col] (#4) circle [radius=\GH@anchor@rad];\fi
}%

\pgfkeys{GHShowGrid/.cd,
color/.code         = \def\GH@grid@col{#1},
space/.code         = \def\GH@grid@space{#1},
step/.code          = \def\GH@grid@step{#1},
precision/.code     = \def\GH@grid@precision{#1}, 
}%

\def\GHShowGrid{\pgfutil@ifnextchar[{\GH@ShowGrid}{\GH@ShowGrid[]}} 
\def\GH@ShowGrid[#1]{%
\pgfkeys{/GHShowGrid/.cd,
color  = lightgray,
space = 0.04,
step=0.1,
precision = 1}
\pgfqkeys{/GHShowGrid}{#1}
\foreach \x in {0,\GH@grid@step,...,1.001}{%
    \draw[\GH@grid@col] (0,\x) ++(-\GH@grid@space,0) node[left]{%
    \pgfmathprintnumber[fixed,fixed zerofill,precision=\GH@grid@precision]
                       {\x}} -- (1,\x);
    \draw[\GH@grid@col] (\x,0) ++(0,-\GH@grid@space)node[rotate=90,left]{%
    \pgfmathprintnumber[fixed,fixed zerofill,precision=\GH@grid@precision]
                       {\x}} -- (\x,1);}}

\pgfkeys{GHspy/.cd,
color/.code         = \def\GH@anchor@col{#1},
}

\def\GHspy#1#2(#3,#4){%
  \spy  on (#1) in node at ([shift={(#3,#4)}]GHimage.#2); 
}
\makeatother

\begin{document}

\begin{tikzpicture}
\tikzset{spy style/.style={spy using outlines={circle, magnification=4, size=3cm, connect spies}}}

\begin{IncludeGH}[12cm]{champignon.jpeg}  
   \GHShowGrid[color=lightgray,step=.1,precision=1]
   \GHAnchor[color=red,radius=2pt,show] at (0.5,0.5){milieu}   
   \GHShowDetail[shape=circle,color=red,width=.2] at (0.25,0.5){cercle}
   \GHShowDetail[shape=rectangle,width=.1,height=.1] at (0.7,0.7){rec}
   \GHspy{cercle}{south}(-4,-3)  
   \GHShowPath[ultra thick,red]{(0.5,0.75) -- (0.90,0.75) -- (0.90,0.5) .. controls (0.8,-0.2) and (0.65,0.2) .. (0.5,0.3)} 
\end{IncludeGH}
\end{tikzpicture}

\begin{tikzpicture}
\begin{IncludeClipGH}[12cm]{champignon.jpeg}  
\GHShowClipPath[red]{(0.5,0.75) -- (0.90,0.75) -- 
    (0.90,0.5) .. controls (0.8,-0.2) and (0.65,0.2) .. (0.5,0.3)} 
\end{IncludeClipGH}
\end{tikzpicture}  
\end{document}

enter image description here

share|improve this answer
add comment

I am not using Bezier. It is just for fun.

\documentclass{article}
\usepackage{graphicx,pstricks,pst-func}

\newsavebox\IBox
\savebox\IBox{\includegraphics[width=\linewidth]{Images/food}}

\newdimen\width
\newdimen\height
\width=\wd\IBox
\height=\ht\IBox

\def\function
{
        \psparametricplot{0}{2.5 .25 exp}{t^2  | 0.8*(sqrt(2.5-t^4)+t)}
        \psparametricplot{2.5 .25 exp}{0}{t^2  | 0.8*(-sqrt(2.5-t^4)+t)}
        \psparametricplot{0}{2.5 .25 exp}{-t^2 | 0.8*(-sqrt(2.5-t^4)+t)}
        \psparametricplot{2.5 .25 exp}{0}{-t^2 | 0.8*(sqrt(2.5-t^4)+t)}
}

\pagestyle{empty}

\begin{document}
\centering
\begin{pspicture}(\width,\height)
    \rput[lb](0,0){\usebox\IBox}
    \pscustom[unit=2.3cm, origin={0.5\width,0.4\height}, linecolor=cyan, dimen=middle, linewidth=3pt, algebraic]{\function}
    \psgrid[gridwidth=0.2pt, gridcolor=white, subgriddiv=1]
\end{pspicture}

\vspace{1cm}
\begin{pspicture}(\width,\height)
    \psclip{\pscustom[unit=2.3cm, origin={0.5\width,0.4\height}, linestyle=none, algebraic]{\function}}
    \rput[lb](0,0){\usebox\IBox}
    \endpsclip
    \psgrid[gridwidth=0.2pt, gridcolor=white, subgriddiv=1]
\end{pspicture}
\end{document}

enter image description here

share|improve this answer
add comment

This is a clipper with bezier curves.

enter image description here

\documentclass[pstricks,border={-8.5mm -5.5mm -8.5mm -5.0mm}]{standalone}
\usepackage{pst-eucl,graphicx}


\psset
{
    runit=\psunit,
    fillstyle=solid,
    PointName=none,
    PointSymbol=none,
}

\pstVerb
{
    /theta 72 def
    /Major 6.0 def
    /Minor 3.3 def
    % b a t p2c ---> x y
    % where b (semi-minor), a (semi-major), t (theta)
    /p2c {dup 3 1 roll cos mul 3 1 roll sin mul} bind def
}

\def\DeclareNodes
{
    \pstGeonode
        (0,-8){Bottom}
        (0,8){Top}
        (0,0){center}
        (0,2.7){A}
        (0.5,2.7){B}
        (1,3.25){C}
        (1.2,1.3){D}
        (1.3,1.0){E}
        (2.0,1.0){F}
        (3.0,1.0){G}
        (3.0,2.2){H}
        (!Minor Major theta p2c){I}
        (!Minor Major theta neg p2c){J}
        (4,-2){K}
        (4,0){L}
        (2.2,-1.8){M}
        (1.5,-1){N}
        (1,-1){O}
        (0,-3.2){P}
    \pstOrtSym{Bottom}{Top}{B,C,D,E,F,G,H,I,J,K,L,M,N,O}
}

\def\RightPart
{
    \psline(A)(B)(C)
    \psbezier(D)(E)(F)
    \psbezier(G)(H)(I)
    \psellipticarcn[dimen=middle](center)(!Major Minor){(I)}{(J)}
    \psbezier(K)(L)(M)
    \psbezier(N)(O)(P)
}


\def\LeftPart
{
    \psbezier(O')(N')(M')
    \psbezier(L')(K')(J')
    \psellipticarcn[dimen=middle](center)(!Major Minor){(J')}{(I')}
    \psbezier(H')(G')(F')
    \psbezier(E')(D')(C')
    \psline(B')
}


\begin{document}


%\begin{pspicture}[showgrid=top](-7,-4)(7,4)
%    \DeclareNodes
%    \pscustom*{\RightPart\LeftPart\closepath}
%\end{pspicture}


\begin{pspicture}[showgrid=false](-7,-4)(7,4)
    \begin{psclip}{\DeclareNodes\pscustom[linewidth=2mm,linecolor=red]{\RightPart\LeftPart\closepath}}
       \rput(0,0){\includegraphics[width=14\psunit]{herbert}}
    \end{psclip}
\end{pspicture}


\end{document}

Edit:

Another similar method can be seen here.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.