Drawing¶

New in version 0.3.0.

The wand.drawing module provides some basic drawing functions. wand.cartoon.Drawing object buffers instructions for cartoon shapes into images, and then information technology can describe these shapes into zero or more images.

Information technology's also callable and takes an Epitome object:

                        from            wand.drawing            import            Drawing            from            wand.prototype            import            Epitome            with            Drawing            ()            as            draw            :            # does something with ``describe`` object,            # and and then...            with            Image            (            filename            =            'wandtests/avails/beach.jpg'            )            equally            prototype            :            draw            (            epitome            )          

Arc¶

New in version 0.four.0.

Arcs tin can be drawn by using arc() method. Yous'll need to ascertain 3 pairs of (ten, y) coordinates. Offset & second pair of coordinates will be the minimum bounding rectangle, and the last pair define the starting & ending degree.

An example:

                            from              wand.paradigm              import              Epitome              from              wand.drawing              import              Drawing              from              wand.colour              import              Color              with              Drawing              ()              equally              depict              :              draw              .              stroke_color              =              Color              (              'black'              )              describe              .              stroke_width              =              2              draw              .              fill_color              =              Color              (              'white'              )              describe              .              arc              ((              25              ,              25              ),              # Stating point              (              75              ,              75              ),              # Ending point              (              135              ,              -              45              ))              # From lesser left effectually to meridian correct              with              Prototype              (              width              =              100              ,              height              =              100              ,              background              =              Color              (              'lightblue'              ))              equally              img              :              draw              .              draw              (              img              )              img              .              save              (              filename              =              'draw-arc.gif'              )            

draw-arc.gif

Bezier¶

New in version 0.four.0.

You can draw bezier curves using bezier() method. This method requires at least four points to determine a bezier curve. Given equally a list of (x, y) coordinates. The starting time & last pair of coordinates are treated equally start & end, and the second & 3rd pair of coordinates deed every bit controls.

For example:

                            from              wand.epitome              import              Image              from              wand.cartoon              import              Drawing              from              wand.color              import              Color              with              Drawing              ()              equally              depict              :              draw              .              stroke_color              =              Color              (              'black'              )              draw              .              stroke_width              =              two              draw              .              fill_color              =              Color              (              'white'              )              points              =              [(              10              ,              50              ),              # Start signal              (              50              ,              10              ),              # First control              (              l              ,              90              ),              # Second command              (              90              ,              50              )]              # Cease bespeak              describe              .              bezier              (              points              )              with              Epitome              (              width              =              100              ,              tiptop              =              100              ,              background              =              Color              (              'lightblue'              ))              every bit              image              :              depict              (              prototype              )            

draw-bezier.gif

Control width & color of curve with the cartoon properties:

  • stroke_color
  • stroke_width

Circle¶

New in version 0.4.0.

You can draw circles using circle() method. Circles are drawn past defining two pairs of (ten, y) coordinates. First coordinate for the center " origin " point, and a second pair for the outer perimeter . For case, the following code draws a circle in the middle of the paradigm :

                            from              wand.prototype              import              Image              from              wand.drawing              import              Drawing              from              wand.color              import              Colour              with              Drawing              ()              as              depict              :              draw              .              stroke_color              =              Color              (              'black'              )              draw              .              stroke_width              =              ii              draw              .              fill_color              =              Colour              (              'white'              )              describe              .              circle              ((              50              ,              l              ),              # Middle point              (              25              ,              25              ))              # Perimeter signal              with              Image              (              width              =              100              ,              height              =              100              ,              groundwork              =              Color              (              'lightblue'              ))              as              image              :              draw              (              image              )            

draw-circle.gif

Color & Matte¶

New in version 0.4.0.

Y'all can draw with colors direct on the coordinate system of an image. Define which color to set by setting fill_color . The behavior of color() is controlled by setting ane of PAINT_METHOD_TYPES paint methods.

  • 'point' alters a unmarried pixel.
  • 'supersede' swaps on color for another. Threshold is influenced past fuzz .
  • 'floodfill' fills area of a color influenced by fuzz .
  • 'filltoborder' fills expanse of a colour until border divers by border_color .
  • 'reset' replaces the whole prototype to a unmarried color.

Case fill all to green boarder:

                            from              wand.drawing              import              Cartoon              from              wand.color              import              Color              with              Cartoon              ()              every bit              draw              :              draw              .              border_color              =              Colour              (              'greenish'              )              depict              .              fill_color              =              Color              (              'blue'              )              depict              .              color              (              fifteen              ,              25              ,              'filltoborder'              )            

The matte() method is identical to the color() method above, but alters the alpha channel of the color expanse selected. Colors can be manipulated, but not replaced.

                            with              Drawing              ()              as              draw              :              draw              .              fill_color              =              None              # or Color('none')              draw              .              matte              (              15              ,              25              ,              'floodfill'              )            

Blended¶

New in version 0.4.0.

Similar to composite_channel() , this composite() method will return a given image on top of the drawing subject image following the COMPOSITE_OPERATORS options. An compositing prototype must exist given with a destination acme , left , width , and height values.

                            from              wand.image              import              Image              ,              COMPOSITE_OPERATORS              from              wand.drawing              import              Drawing              from              wand.brandish              import              display              wizard              =              Image              (              filename              =              'wizard:'              )              rose              =              Prototype              (              filename              =              'rose:'              )              for              o              in              COMPOSITE_OPERATORS              :              due west              =              wizard              .              clone              ()              r              =              rose              .              clone              ()              with              Drawing              ()              every bit              draw              :              describe              .              composite              (              operator              =              o              ,              left              =              175              ,              top              =              250              ,              width              =              r              .              width              ,              superlative              =              r              .              superlative              ,              prototype              =              r              )              draw              (              w              )              brandish              (              w              )            

Ellipse¶

New in version 0.4.0.

Ellipse tin exist fatigued by using the ellipse() method. Similar drawing circles, the ellipse requires a origin indicate, notwithstanding, a pair of (x, y) radius are used in relationship to the origin coordinate. Past default a complete "closed" ellipse is drawn. To describe a partial ellipse, provide a pair of starting & ending degrees equally the third parameter.

An example of a total ellipse:

                            from              wand.epitome              import              Image              from              wand.cartoon              import              Drawing              from              wand.color              import              Colour              with              Cartoon              ()              equally              draw              :              draw              .              stroke_color              =              Color              (              'black'              )              draw              .              stroke_width              =              2              draw              .              fill_color              =              Color              (              'white'              )              draw              .              ellipse              ((              50              ,              l              ),              # Origin (center) indicate              (              forty              ,              20              ))              # 80px broad, and 40px tall              with              Image              (              width              =              100              ,              height              =              100              ,              background              =              Colour              (              'lightblue'              ))              as              epitome              :              draw              (              image              )            

draw-ellipse-full.gif

Same example every bit to a higher place, simply with a half-fractional ellipse defined by the third parameter:

                            describe              .              ellipse              ((              50              ,              50              ),              # Origin (center) point              (              xl              ,              20              ),              # 80px wide, and 40px alpine              (              90              ,              -              90              ))              # Draw half of ellipse from lesser to top            

draw-ellipse-part.gif

Lines¶

Yous tin describe lines using line() method. Information technology simply takes ii (x, y) coordinates for start and end of a line. For instance, the following code draws a diagonal line into the epitome :

                            draw              .              line              ((              0              ,              0              ),              image              .              size              )              draw              (              image              )            

Or you can turn this diagonal line upside downwardly:

                            draw              .              line              ((              0              ,              prototype              .              height              ),              (              paradigm              .              width              ,              0              ))              draw              (              image              )            

The line colour is determined by fill_color belongings, and you lot tin change this of grade. The post-obit lawmaking draws a red diagonal line into the image :

                            from              wand.color              import              Color              with              Colour              (              'red'              )              as              color              :              draw              .              fill_color              =              color              draw              .              line              ((              0              ,              0              ),              image              .              size              )              depict              (              prototype              )            

Paths¶

New in version 0.iv.0.

Paths can be drawn by using any collection of path functions between path_start() and path_finish() methods. The available path functions are:

  • path_close() draws a path from terminal point to starting time.
  • path_curve() draws a cubic bezier bend.
  • path_curve_to_quadratic_bezier() draws a quadratic bezier curve.
  • path_elliptic_arc() draws an elliptical arc.
  • path_horizontal_line() draws a horizontal line.
  • path_line() draws a line path.
  • path_move() arrange current point without drawing.
  • path_vertical_line() draws a vertical line.

Each path method expects a destination point, and will describe from the current point to the new indicate. The destination betoken will get the new electric current bespeak for the next applied path method. Destination points are given in the form of ( ten , y ) coordinates to the to parameter, and can by relative or absolute to the current indicate past setting the relative flag. The path_curve() and path_curve_to_quadratic_bezier() expect additional control points, and can complement previous drawn curves by setting a smooth flag. When the smoothen flag is set to True the get-go control point is causeless to exist the reflection of the last divers control point.

For example:

                            from              wand.image              import              Image              from              wand.drawing              import              Drawing              from              wand.colour              import              Color              with              Drawing              ()              equally              draw              :              draw              .              stroke_width              =              two              draw              .              stroke_color              =              Color              (              'blackness'              )              describe              .              fill_color              =              Colour              (              'white'              )              draw              .              path_start              ()              # Outset heart-left              depict              .              path_move              (              to              =              (              x              ,              50              ))              # Curve accross top-left to center              draw              .              path_curve              (              to              =              (              forty              ,              0              ),              controls              =              [(              x              ,              -              40              ),              (              30              ,              -              xl              )],              relative              =              True              )              # Continue bend accross bottom-right              draw              .              path_curve              (              to              =              (              forty              ,              0              ),              controls              =              (              xxx              ,              40              ),              shine              =              True              ,              relative              =              Truthful              )              # Line to top-correct              draw              .              path_vertical_line              (              10              )              # Diagonal line to bottom-left              describe              .              path_line              (              to              =              (              ten              ,              90              ))              # Close first & final points              describe              .              path_close              ()              draw              .              path_finish              ()              with              Image              (              width              =              100              ,              height              =              100              ,              background              =              Color              (              'lightblue'              ))              as              paradigm              :              draw              (              epitome              )            

draw-path.gif

Point¶

New in version 0.four.0.

You lot tin can draw points by using point() method. It simply takes two x , y arguments for the point coordinate.

The post-obit example will draw points following a math part across a given image :

                            from              wand.image              import              Epitome              from              wand.cartoon              import              Cartoon              from              wand.color              import              Color              import              math              with              Drawing              ()              as              draw              :              for              x              in              xrange              (              0              ,              100              ):              y              =              math              .              tan              (              x              )              *              4              draw              .              point              (              x              ,              y              +              50              )              with              Image              (              width              =              100              ,              height              =              100              ,              background              =              Color              (              'lightblue'              ))              as              image              :              draw              (              epitome              )            

draw-point-math.gif

Colour of the indicate tin be divers past setting the following property

  • fill_color

Polygon¶

New in version 0.4.0.

Complex shapes can exist created with the polygon() method. Y'all can draw a polygon past given this method a listing of points. Stroke line volition automatically close between first & last point.

For instance, the following code volition draw a triangle into the prototype :

                            from              wand.image              import              Image              from              wand.drawing              import              Cartoon              from              wand.color              import              Color              with              Drawing              ()              equally              describe              :              draw              .              stroke_width              =              two              describe              .              stroke_color              =              Color              (              'black'              )              describe              .              fill_color              =              Colour              (              'white'              )              points              =              [(              25              ,              25              ),              (              75              ,              fifty              ),              (              25              ,              75              )]              depict              .              polygon              (              points              )              with              Image              (              width              =              100              ,              superlative              =              100              ,              background              =              Color              (              'lightblue'              ))              as              image              :              describe              (              paradigm              )            

draw-polygon.gif

Control the fill & stroke with the following backdrop:

  • stroke_color
  • stroke_dash_array
  • stroke_dash_offset
  • stroke_line_cap
  • stroke_line_join
  • stroke_miter_limit
  • stroke_opacity
  • stroke_width
  • fill_color
  • fill_opacity
  • fill_rule

Button & Popular¶

New in version 0.iv.0.

When working with complex vector graphics, you lot tin can utilise ImageMagick's internal graphic-context stack to manage unlike styles & operations. The methods button() , push_clip_path() , push_defs() , and push_pattern() are used to marking the get-go of a sub-routine. The prune path & pattern methods accept a name based identifier argument, and tin can be referenced at a latter signal with clip_path , or set_fill_pattern_url() / set_stroke_pattern_url() respectively. With stack management, pop() is used to mark the end of a sub-routine, and return the graphical context to its pervious state before push() was invoked. Methods pop_clip_path() , pop_defs() , and pop_pattern() be to match there pop counterparts.

                            from              wand.color              import              Color              from              wand.image              import              Image              from              wand.drawing              import              Drawing              from              wand.compat              import              nested              from              math              import              cos              ,              pi              ,              sin              with              nested              (              Colour              (              'lightblue'              ),              Colour              (              'transparent'              ),              Drawing              ())              as              (              bg              ,              fg              ,              describe              ):              draw              .              stroke_width              =              3              draw              .              fill_color              =              fg              for              caste              in              range              (              0              ,              360              ,              15              ):              draw              .              push              ()              # Grow stack              draw              .              stroke_color              =              Color              (              'hsl(              {0}              %, 100%, l%)'              .              format              (              degree              *              100              /              360              ))              t              =              caste              /              180.0              *              pi              x              =              35              *              cos              (              t              )              +              50              y              =              35              *              sin              (              t              )              +              l              depict              .              line              ((              50              ,              50              ),              (              10              ,              y              ))              draw              .              pop              ()              # Restore stack              with              Prototype              (              width              =              100              ,              height              =              100              ,              background              =              Color              (              'lightblue'              ))              as              img              :              draw              (              img              )            

../_images/draw-push-pop.gif

Rectangles¶

New in version 0.3.6.

Changed in version 0.4.0.

If yous want to draw rectangles use rectangle() method. Information technology takes left / elevation coordinate, and right / bottom coordinate, or width and peak . For case, the following code draws a square on the epitome :

                            draw              .              rectangle              (              left              =              10              ,              top              =              10              ,              right              =              40              ,              bottom              =              40              )              draw              (              image              )            

Or using width and height instead of right and bottom :

                            draw              .              rectangle              (              left              =              ten              ,              meridian              =              10              ,              width              =              30              ,              pinnacle              =              thirty              )              depict              (              image              )            

Support for rounded corners was added in version 0.4.0. The radius argument sets corner rounding.

                            depict              .              rectangle              (              left              =              ten              ,              top              =              10              ,              width              =              thirty              ,              height              =              30              ,              radius              =              five              )              describe              (              image              )            

Both horizontal & vertical tin can be set independently with xradius & yradius respectively.

                            draw              .              rectangle              (              left              =              10              ,              top              =              10              ,              width              =              30              ,              height              =              xxx              ,              xradius              =              five              ,              yradius              =              3              )              depict              (              prototype              )            

Note that the stoke and the make full are adamant by the following properties:

  • stroke_color
  • stroke_dash_array
  • stroke_dash_offset
  • stroke_line_cap
  • stroke_line_join
  • stroke_miter_limit
  • stroke_opacity
  • stroke_width
  • fill_color
  • fill_opacity
  • fill_rule

Texts¶

Drawing object tin write texts too using its text() method. Information technology takes x and y coordinates to be drawn and a string to write:

                            draw              .              font              =              'wandtests/assets/League_Gothic.otf'              draw              .              font_size              =              forty              draw              .              text              (              image              .              width              /              two              ,              image              .              height              /              2              ,              'Hello, world!'              )              draw              (              image              )            

Equally the to a higher place code shows you can accommodate several settings before writing texts:

  • font
  • font_family
  • font_resolution
  • font_size
  • font_stretch
  • font_style
  • font_weight
  • gravity
  • text_alignment
  • text_antialias
  • text_decoration
  • text_direction
  • text_interline_spacing
  • text_interword_spacing
  • text_kerning
  • text_under_color

Discussion Wrapping¶

The Drawing class, by nature, doesn't implement any course of word-wrapping, and users of the wand library would be responsible for implementing this behavior unique to their concern requirements.

ImageMagick's caption: coder does offer a word-wrapping solution with Paradigm.caption() method, simply Python's textwrap is a little more sophisticated.

                            from              textwrap              import              wrap              from              wand.color              import              Color              from              wand.drawing              import              Drawing              from              wand.image              import              Image              def              draw_roi              (              contxt              ,              roi_width              ,              roi_height              ):              """Allow's draw a blue box then we can identify what                              our region of intrest is."""              ctx              .              push              ()              ctx              .              stroke_color              =              Color              (              'BLUE'              )              ctx              .              fill_color              =              Color              (              'TRANSPARENT'              )              ctx              .              rectangle              (              left              =              75              ,              summit              =              255              ,              width              =              roi_width              ,              tiptop              =              roi_height              )              ctx              .              pop              ()              def              word_wrap              (              image              ,              ctx              ,              text              ,              roi_width              ,              roi_height              ):              """Break long text to multiple lines, and reduce signal size                              until all text fits inside a bounding box."""              mutable_message              =              text              iteration_attempts              =              100              def              eval_metrics              (              txt              ):              """Quick helper function to calculate width/height of text."""              metrics              =              ctx              .              get_font_metrics              (              image              ,              txt              ,              True              )              return              (              metrics              .              text_width              ,              metrics              .              text_height              )              while              ctx              .              font_size              >              0              and              iteration_attempts              :              iteration_attempts              -=              1              width              ,              superlative              =              eval_metrics              (              mutable_message              )              if              height              >              roi_height              :              ctx              .              font_size              -=              0.75              # Reduce pointsize              mutable_message              =              text              # Restore original text              elif              width              >              roi_width              :              columns              =              len              (              mutable_message              )              while              columns              >              0              :              columns              -=              1              mutable_message              =              '              \northward              '              .              bring together              (              wrap              (              mutable_message              ,              columns              ))              wrapped_width              ,              _              =              eval_metrics              (              mutable_message              )              if              wrapped_width              <=              roi_width              :              intermission              if              columns              <              1              :              ctx              .              font_size              -=              0.75              # Reduce pointsize              mutable_message              =              text              # Restore original text              else              :              pause              if              iteration_attempts              <              one              :              raise              RuntimeError              (              "Unable to calculate word_wrap for "              +              text              )              return              mutable_message              message              =              """This is some really long sentence with the                              word "Mississippi" in it."""              ROI_SIDE              =              175              with              Image              (              filename              =              'logo:'              )              as              img              :              with              Drawing              ()              as              ctx              :              draw_roi              (              ctx              ,              ROI_SIDE              ,              ROI_SIDE              )              # Set the font style              ctx              .              fill_color              =              Colour              (              'Ruddy'              )              ctx              .              font_family              =              'Times New Roman'              ctx              .              font_size              =              32              mutable_message              =              word_wrap              (              img              ,              ctx              ,              message              ,              ROI_SIDE              ,              ROI_SIDE              )              ctx              .              text              (              75              ,              275              ,              mutable_message              )              ctx              .              draw              (              img              )              img              .              save              (              filename              =              'draw-discussion-wrap.png'              )            

../_images/draw-word-wrap.png