The ctypes-based simple ImageMagick binding for Python

Overview

https://docs.wand-py.org/en/latest/_static/wand.png

Wand

Wand is a ctypes-based simple ImageMagick binding for Python, supporting 2.7, 3.3+, and PyPy. All functionalities of MagickWand API are implemented in Wand.

You can install the package from PyPI by using pip:

$ pip install Wand

Or would you like to enjoy the bleeding edge? Check out the head revision of the source code from the GitHub repository:

$ git clone git://github.com/emcconville/wand.git
$ cd wand/
$ python setup.py install

Docs

Recent version
https://docs.wand-py.org/
Development version

https://docs.wand-py.org/en/latest/

Documentation Status

Community

Website
http://wand-py.org/
GitHub
https://github.com/emcconville/wand
Package Index (Cheeseshop)

https://pypi.python.org/pypi/Wand

Latest PyPI version
Discord
https://discord.gg/BWQ25wB
Stack Overflow tag (Q&A)
http://stackoverflow.com/questions/tagged/wand
Continuous Integration (Travis CI)

https://travis-ci.org/emcconville/wand

Build Status
Continuous Integration (GitHub Actions)

https://github.com/emcconville/wand/actions

Build Status
Code Coverage

https://coveralls.io/r/emcconville/wand

https://coveralls.io/repos/github/emcconville/wand/badge.svg?branch=master
Comments
  • MagickWand shared library not found

    MagickWand shared library not found

    Exception information:

    Traceback (most recent call last):
      File "testss.py", line 1, in <module>
        from wand.image import Image
      File "/Users/hit9/spam/testfirfffff/venv/lib/python2.7/site-packages/wand/image.py", line 20, in <module>
        from .api import MagickPixelPacket, libc, libmagick, library
      File "/Users/hit9/spam/testfirfffff/venv/lib/python2.7/site-packages/wand/api.py", line 156, in <module>
        'Try to install:\n  ' + msg)
    ImportError: MagickWand shared library not found.
    You probably had not installed ImageMagick library.
    Try to install:
      brew install imagemagick
    

    I am using OSX10.8

    And I installed imagemagick via brew:

    $ brew install imagemagick
    Warning: imagemagick-6.8.6-3 already installed
    

    And here is my result run ls in /usr/local/lib :

    $ ls -l  /usr/local/lib/ | grep libMagick
    lrwxr-xr-x   1 hit9  admin       59 Aug 22 11:04 libMagick++-6.Q16.1.dylib -> ../Cellar/imagemagick/6.8.6-3/lib/libMagick++-6.Q16.1.dylib
    lrwxr-xr-x   1 hit9  admin       57 Aug 22 11:04 libMagick++-6.Q16.dylib -> ../Cellar/imagemagick/6.8.6-3/lib/libMagick++-6.Q16.dylib
    lrwxr-xr-x   1 hit9  admin       54 Aug 22 11:04 libMagick++-6.Q16.la -> ../Cellar/imagemagick/6.8.6-3/lib/libMagick++-6.Q16.la
    lrwxr-xr-x   1 hit9  admin       61 Aug 22 11:04 libMagickCore-6.Q16.1.dylib -> ../Cellar/imagemagick/6.8.6-3/lib/libMagickCore-6.Q16.1.dylib
    lrwxr-xr-x   1 hit9  admin       59 Aug 22 11:04 libMagickCore-6.Q16.dylib -> ../Cellar/imagemagick/6.8.6-3/lib/libMagickCore-6.Q16.dylib
    lrwxr-xr-x   1 hit9  admin       56 Aug 22 11:04 libMagickCore-6.Q16.la -> ../Cellar/imagemagick/6.8.6-3/lib/libMagickCore-6.Q16.la
    lrwxr-xr-x   1 hit9  admin       61 Aug 22 11:04 libMagickWand-6.Q16.1.dylib -> ../Cellar/imagemagick/6.8.6-3/lib/libMagickWand-6.Q16.1.dylib
    lrwxr-xr-x   1 hit9  admin       59 Aug 22 11:04 libMagickWand-6.Q16.dylib -> ../Cellar/imagemagick/6.8.6-3/lib/libMagickWand-6.Q16.dylib
    lrwxr-xr-x   1 hit9  admin       56 Aug 22 11:04 libMagickWand-6.Q16.la -> ../Cellar/imagemagick/6.8.6-3/lib/libMagickWand-6.Q16.la
    lrwxr-xr-x   1 hit9  admin       42 Aug 22 11:42 libMagickWand.dylib -> /usr/local/lib/libMagickWand-6.Q16.1.dylib
    

    I noticed there was a few issues similar to this. But I tried the solutions, and issue still exists. Hope your solution, thanks.

    bug 
    opened by hit9 37
  • mountain lion install problem

    mountain lion install problem

    Hello,

    Maybe I'm missing a step, but I got the same result on multiple machines:

    sudo port install ImageMagick => successful sudo easy_install wand => successful

    then in python interactive mode: from wand.image import Image

    throws error:

    Traceback (most recent call last): File "", line 1, in File "build/bdist.macosx-10.8-intel/egg/wand/image.py", line 19, in File "build/bdist.macosx-10.8-intel/egg/wand/api.py", line 266, in ImportError: MagickWand shared library not found or incompatible

    Am I missing a step?

    Thanks!

    bug dist 
    opened by scottgwald 28
  • Refactor C-API loading, and ImageMagick 7 Support

    Refactor C-API loading, and ImageMagick 7 Support

    This is a work-in-progress, and should not be merged. I'm opening this pull request for greater visibility, and seek testing help.

    This merge request reworked all C-API method mappings into a directory/module structure mimicking ImageMagick's C headers.

    The primary benefit was to reduce the complexity of the unorganized wand.api.library, and to incorporate all MagickWand 6/7 methods.

    The secondary goal is to include ImageMagick 7 support. For the most part, this has been completed with a few minor TODOs.

    Overview of Changes

    • C-API methods have been moved to the following structure.
      wand.api.cdefs
                    .core              All MagickCore definitions.
                    .drawing_wand      <drawing-wand.h> methods.
                    .magick_image      <magick-image.h> methods.
                    .magick_property   <magick-property.h> methods.
                    .magick_wand       <magick-wand.h> methods.
                    .pixel_iterator    <pixel-iterrator.h> methods.
                    .pixel_wand        <pixel-wand.h> methods.
                    .structures        Collection of ctypes.Structure definitions.
                    .wandtypes         Ctype portability wrappers like `c_magick_char_p'
      
    • PixelInfo replaces MagickPixelPacket
    • HDRI support
    • Implemented MagickSetImageChannelMask to replace Magick{XXXX}Channel methods.

    Outstanding Items

    • [x] Rewrite wand.image.Image.transform as MagickTransformImage has been removed in IM 7.
    • [x] Revisite all methods/documentation for MagickCompositeImage. IM 7 is now more "aware" of dynamic channels; so naturally, behavior around Image.composite_channel, Image.composite, Image.transparentize, and Image.watermark should be reviewed.
    • [x] Same for Image.alpha_channel property.
    • [x] Rewrite regressions test marked XFAIL
    • [ ] Documentation. Including all "?.?.?" version placeholders.

    Help with...

    I personally have run out of free time to finish this effort, and would love some help of the following.

    • Performance & Architecture Design. With all MagickWand methods mapped, is wand load time traumatically affected? Is python-caching working in an optimized manner?
    • Regression testing & CI. Ensure ImageMagick-6 continues to work as expected, and/or update Travis builds to include ImageMagick-7 + delegates.
    opened by emcconville 24
  • Memory leak with sequences

    Memory leak with sequences

    The following code eats all your memory in a matter of seconds:

    from wand.color import Color
    from wand.image import Image
    
    while True:
        ri = Image(width=1000, height=1000, background=Color('red'))
        bi = Image(width=1000, height=1000, background=Color('blue'))
        gi = Image(width=1000, height=1000, background=Color('green'))
    
        container = Image(width=1000, height=1000)
        container.sequence.append(ri)
        container.sequence.append(bi)
        container.sequence.append(gi)
    
        container.format = 'gif'
        container.save(filename='/dev/null')
    
        ri.destroy()
        bi.destroy()
        gi.destroy()
        for frame in container.sequence:
            frame.destroy()
        container.destroy()
    
        print('saved')
    

    Is it a bug? How can I destroy all the images so the memory is freed? (I'm supposedly destroying them all, but it's not working)

    bug 
    opened by wodim 21
  • Fully integrate DrawingWand C-API

    Fully integrate DrawingWand C-API

    Originally a PU for adding a few methods I needed for whatever project, this drawing_pu turned into a general effort to integrate all ImageMagick's drawing wand methods. This request is open for code-review, feedback, and improved documents.

    Drawing API Integration Status

    • [x] ClearDrawingWand
    • [x] CloneDrawingWand
    • [x] DestroyDrawingWand
    • [x] DrawAffine
    • [x] DrawAnnotation
    • [x] DrawArc
    • [x] DrawBezier
    • [x] DrawCircle
    • [x] DrawClearException
    • [x] DrawComposite
    • [x] DrawColor
    • [x] DrawComment
    • [x] DrawEllipse
    • [x] DrawGetBorderColor
    • [x] DrawGetClipPath
    • [x] DrawGetClipRule
    • [x] DrawGetClipUnits
    • [x] DrawGetException
    • [ ] DrawGetExceptionType (Never needed as python manages exceptions)
    • [x] DrawGetFillColor
    • [x] DrawGetFillOpacity
    • [x] DrawGetFillRule
    • [x] DrawGetFont
    • [x] DrawGetFontFamily
    • [x] DrawGetFontResolution
    • [x] DrawGetFontSize
    • [x] DrawGetFontStretch
    • [x] DrawGetFontStyle
    • [x] DrawGetFontWeight
    • [x] DrawGetGravity
    • [x] DrawGetOpacity
    • [x] DrawGetStrokeAntialias
    • [x] DrawGetStrokeColor
    • [x] DrawGetStrokeDashArray
    • [x] DrawGetStrokeDashOffset
    • [x] DrawGetStrokeLineCap
    • [x] DrawGetStrokeLineJoin
    • [x] DrawGetStrokeMiterLimit
    • [x] DrawGetStrokeOpacity
    • [x] DrawGetStrokeWidth
    • [x] DrawGetTextAlignment
    • [x] DrawGetTextAntialias
    • [x] DrawGetTextDecoration
    • [x] DrawGetTextDirection
    • [x] DrawGetTextEncoding
    • [x] DrawGetTextKerning
    • [x] DrawGetTextInterlineSpacing
    • [x] DrawGetTextInterwordSpacing
    • [x] DrawGetVectorGraphics
    • [x] DrawGetTextUnderColor
    • [x] DrawLine
    • [x] DrawMatte
    • [x] DrawPathClose
    • [x] DrawPathCurveToAbsolute
    • [x] DrawPathCurveToRelative
    • [x] DrawPathCurveToQuadraticBezierAbsolute
    • [x] DrawPathCurveToQuadraticBezierRelative
    • [x] DrawPathCurveToQuadraticBezierSmoothAbsolute
    • [x] DrawPathCurveToQuadraticBezierSmoothRelative
    • [x] DrawPathCurveToSmoothAbsolute
    • [x] DrawPathCurveToSmoothRelative
    • [x] DrawPathEllipticArcAbsolute
    • [x] DrawPathEllipticArcRelative
    • [x] DrawPathFinish
    • [x] DrawPathLineToAbsolute
    • [x] DrawPathLineToRelative
    • [x] DrawPathLineToHorizontalAbsolute
    • [x] DrawPathLineToHorizontalRelative
    • [x] DrawPathLineToVerticalAbsolute
    • [x] DrawPathLineToVerticalRelative
    • [x] DrawPathMoveToAbsolute
    • [x] DrawPathMoveToRelative
    • [x] DrawPathStart
    • [x] DrawPoint
    • [x] DrawPolygon
    • [x] DrawPolyline
    • [x] DrawPopClipPath
    • [x] DrawPopDefs
    • [x] DrawPopPattern
    • [x] DrawPushClipPath
    • [x] DrawPushDefs
    • [x] DrawPushPattern
    • [x] DrawRectangle
    • [x] DrawResetVectorGraphics
    • [x] DrawRotate
    • [x] DrawRoundRectangle (Integrate with rectangle method)
    • [x] DrawScale
    • [x] DrawSetBorderColor
    • [x] DrawSetClipPath
    • [x] DrawSetClipRule
    • [x] DrawSetClipUnits
    • [x] DrawSetFillColor
    • [x] DrawSetFillOpacity
    • [x] DrawSetFontResolution
    • [x] DrawSetOpacity
    • [x] DrawSetFillPatternURL
    • [x] DrawSetFillRule
    • [x] DrawSetFont
    • [x] DrawSetFontFamily
    • [x] DrawSetFontSize
    • [x] DrawSetFontStretch
    • [x] DrawSetFontStyle
    • [x] DrawSetFontWeight
    • [x] DrawSetGravity
    • [x] DrawSetStrokeColor
    • [x] DrawSetStrokePatternURL
    • [x] DrawSetStrokeAntialias
    • [x] DrawSetStrokeDashArray
    • [x] DrawSetStrokeDashOffset
    • [x] DrawSetStrokeLineCap
    • [x] DrawSetStrokeLineJoin
    • [x] DrawSetStrokeMiterLimit
    • [x] DrawSetStrokeOpacity
    • [x] DrawSetStrokeWidth
    • [x] DrawSetTextAlignment
    • [x] DrawSetTextAntialias
    • [x] DrawSetTextDecoration
    • [x] DrawSetTextDirection
    • [x] DrawSetTextEncoding
    • [x] DrawSetTextKerning
    • [x] DrawSetTextInterlineSpacing
    • [x] DrawSetTextInterwordSpacing
    • [x] DrawSetTextUnderColor
    • [x] DrawSetVectorGraphics
    • [x] DrawSkewX
    • [x] DrawSkewY
    • [x] DrawTranslate
    • [x] DrawSetViewbox
    • [x] IsDrawingWand
    • [x] NewDrawingWand
    • [ ] ~~~PeekDrawingWand~~~ (requires building DrawInfo struct, and this is not helpful until other drawing-info methods are exposed to the C-API)
    • [x] PopDrawingWand
    • [x] PushDrawingWand

    Original PU Overview

    • Created PointInfo struct reference in API type casting.
    • Assigned / mapped arguments for wand library methods.
    • Completed initial unit test & documentation.

    Examples

    Drawing.polygon

    with Image(filename="crosshatch.png") as img:
        with Drawing() as draw:
            draw.fill_color = Color("#fff")
            draw.stroke_color = Color("#000")
            draw.stroke_width = 2
            points = [(5,5),(45,40),(45,10),(5,45)]
            draw.polygon(points)
            draw.draw(img)
            img.save(filename="polygon.png")
    

    Drawing.polygon

    Drawing.polyline

    with Image(filename="crosshatch.png") as img:
        with Drawing() as draw:
            draw.fill_color = Color("transparent")
            draw.stroke_color = Color("#000")
            draw.stroke_width = 2
            points = [(5,5),(45,40),(45,10),(5,45)]
            draw.polyline(points)
            draw.draw(img)
            img.save(filename="polyline.png")
    

    Drawing.polyline

    Drawing.bezier

    with Image(filename="crosshatch.png") as img:
        with Drawing() as draw:
            draw.fill_color = Color("transparent")
            draw.stroke_color = Color("#000")
            draw.stroke_width = 2
            points = [(5,5), (0,50), (50,0), (45,45)]
            draw.bezier(points)
            draw.draw(img)
            img.save(filename="bezier.png")
    

    Drawing.bezier

    opened by emcconville 20
  • Support color map / palette manipulation

    Support color map / palette manipulation

    The "colorMap" and "colorMapSize" attributes of the Image class are not available for reading / writing (or I missed them in the docs) so you can't get / set the palette of an image.

    opened by HorstBaerbel 17
  • Inconsistent behavior when dealing with alpha channels and tiffs

    Inconsistent behavior when dealing with alpha channels and tiffs

    This is related to #468 so if you want to close this and re-open that, that's fine by me.

    I'm using wand 0.6.2, and when I use the PDF still attached to #468 , and run that example code I posted, (I tried both setting alpha_channel to off and False) I get something far weirder (see attached). The original fix that was posted to stackoverflow also no longer works (but I think that's expected because you now handle it internally).

    Some sample code:

    This works:

    
    with Image(filename='5-page-pdf.pdf') as img:
        img.type = "grayscale"
        img.format = "tiff"
        img.compression = "lzw"
        img.alpha_channel = 'off'
        img.save(filename="test.tiff")
    
    

    This does not:

    
    with Image(filename='5-page-pdf.pdf') as img:
        img.type = "grayscale"
        img.format = "tiff"
        img.compression = "lzw"
        img.alpha_channel = False
        img.save(filename="test.tiff")
    
    

    I've noticed that some TIFF viewers enhance images more than others, the Preview application on macOS is pretty barebones and doesn't do anything to make the TIFF nicer, so the difference between the working and non working examples is that the non working example only has the first and last page with the alpha channel correctly set to off. (When Windows loads the TIFF using Windows Photo Viewer, it looks correct, but I believe its not showing the raw tiff). Not a major deal, I can just use "off", I just expected False to work based on the docs.

    This also does not work, but the result is far weirder and likely a bug (TIFF output also attached):

    
    blob = Image(filename='5-page-pdf.pdf').make_blob()
    
    with Image(blob=blob) as img:
        img.type = "grayscale"
        img.format = "tiff"
        img.compression = "lzw"
        img.alpha_channel = 'off'
        img.save(filename="test.tiff")
    
    

    As you can see, the alpha channel is removed, but each page is scaled down and repeated 3 times horizontally on its respective page. Very bizarre

    The tiff showing the difference between "off" and False. (The version using off looks correct so I didnt bother posting it).

    The tiff showing the result of loading an image as a blob and then trying to remove the alpha channel

    doc upstream-issue 
    opened by bmoscon 16
  • No way to change image colorspace

    No way to change image colorspace

    I am using wand to convert a CMYK PDF to an sRGB png.

    Here's a sample CMYK PDF: https://dl.dropboxusercontent.com/u/15672/dndel/in.pdf (sorry, github doesn't allow me to add a pdf directly to an issue).

    When I use imagemagick on the command line:

    convert in.pdf out1.png
    

    I get: out1

    which is bad. Instead, I have to change the colorspace, so if I do

    convert -colorspace sRGB in.pdf out2.png
    

    I get: out2

    which is good.

    As far as I can tell, there's no way to set colorspace in Wand.

    When I run

    from wand.image import Image
    
    with Image(filename='in.pdf') as img:
        with img.convert('png') as converted:
            converted.save(filename='out3.png')
    

    I get the same as the first convert: out3

    It would be nice if Wand supported colorspace-- many PDFs and other print documents use CMYK.

    bug 
    opened by srubin 16
  • Fix travis tests

    Fix travis tests

    I think these requirements conflict with the setup.py ones.

    https://github.com/pypa/pip/issues/1197 <- I added the test deps to extras_require so pip install -e .[test] works as expected.

    opened by orf 15
  • Support numpy's __array_interface__

    Support numpy's __array_interface__

    It would be nice if you could provide a wand image to numpy.asarray() and have it automatically create a properly sized and shaped numpy matrix.

    Right now if you try to pass an image in, things bog down and 100% CPU is used. I suspect this is due to the iteration interface on wand.image.Image creating a Color object for every pixel.

    To support this, Wand would need to have a __array_interface__ property which returned some information about the data. You can find some information on the interface at http://scipy-lectures.github.com/advanced/advanced_numpy/index.html#array-interface-protocol

    Basically, I think something like this would work, at least for raw RGB:

    with Image.open(filename="/tmp/some.jpg") as img:
        array = numpy.asarray(img)
    

    And the __array_interface__ would be something like:

    @property
    def __array_interface__(self):
        return dict(data=self.make_blob("RGB"),
                    shape=(self.width, self.height, 3),
                    typestr="|u1")
    

    You might want to use the image's internal format so you could support things like RGBA; I'm not sure what the right thing to do here is. (And in that case, shape would be 4 for the third argument.)

    enhance 
    opened by joeshaw 15
  • Sequences api

    Sequences api

    A new Sequence object is created as image.sequence property in Image constructor.

    Here are some use cases of api:

    >>> # Load 4-imaged apple's icon
    >>> import requests
    >>> r = requests.get('http://apple.com/favicon.ico')
    >>> from wand.image import Image
    >>> img = Image(blob=r.content, format='ico')
    >>> # Get sequenses length
    >>> print len(img.sequence)
    4
    >>> # Print images sizes at sequence
    >>> for i in img.sequence:
    ...     print (i, img.size)
    ...     
    ... 
    (0L, (32L, 32L))
    (1L, (16L, 16L))
    (2L, (32L, 32L))
    (3L, (16L, 16L))
    >>> # Set third image as current (every changes would be applied to it)
    >>> img.sequence.index = 2
    >>> # Delete all images exept the first one
    >>> for i in range(3, 0, -1):
    ...     img.sequence.index = i
    ...     del img.sequence.index
    ...     
    ... 
    >>> print len(img.sequence)
    1
    >>> # Append a copy of our image before current image
    >>> img2 = img.clone()
    >>> img.sequence.append(img.clone(), True)
    >>> print(len(img.sequence))
    2
    
    enhance 
    opened by wronglink 15
  • Switch from py.path to pathlib/pathlib2

    Switch from py.path to pathlib/pathlib2

    Hi, In addition to https://github.com/emcconville/wand/pull/607, py.local is deprecated and pathlib or pathlib2 should be used instead of this: https://github.com/emcconville/wand/blob/3eeb75734ac6b6f4d703ba3562c517a20b19be3c/tests/conftest.py#L11

    From the pytest doc:

    The tmpdir and tmpdir_factory fixtures are similar to tmp_path and tmp_path_factory, but use/return legacy py.path.local_ objects rather than standard :class:pathlib.Path objects.

    From the py doc:

    Note: The ‘py’ library is in “maintenance mode” and so is not recommended for new projects. Please check out pathlib or pathlib2 for path operations.

    opened by sbraz 2
  • Drawing Rounded Rectangle does not work if pyplot used / or

    Drawing Rounded Rectangle does not work if pyplot used / or "unlucky dimensions" entered

    I'm running Ubuntu 21.10, Python 3.9.7 and Wand 0.6.7. There is an issue if my python code first does some pyplot stuff and then drawing an rounded rectangle using wand.

    The following code does not throw any error message, however the resulting file output.png is empty (NO green rectangle is drawn):

    from wand.image import Image
    from wand.drawing import Drawing
    from wand.color import Color
    
    # do some pyplot stuff
    import matplotlib.pyplot as plt
    plt.plot([1, 2, 3, 4])
    
    # Do some wand stuff
    img = Image(width=850, height=600) # This dimension does NOT work
    with Drawing() as drw:
    	drw.fill_color = Color('green')
    	drw.rectangle(left=0,
    				top=0,
    				width=img.width,
    				height=img.height,
    				radius=img.width*0.05)
    	drw(img)
    img.save(filename='output.png')
    

    Now the strange part. The code works fine if I remove seemingly unrelated pyplot stuff at the beginning:

    from wand.image import Image
    from wand.drawing import Drawing
    from wand.color import Color
    
    # Do some wand stuff
    img = Image(width=850, height=600) # This dimension does NOT work
    with Drawing() as drw:
    	drw.fill_color = Color('green')
    	drw.rectangle(left=0,
    				top=0,
    				width=img.width,
    				height=img.height,
    				radius=img.width*0.05)
    	drw(img)
    img.save(filename='output.png')
    

    Now the super crazy thing: I don't need to remove the pyplot stuff, because I can also make the code running by simply changing the dimensions:

    from wand.image import Image
    from wand.drawing import Drawing
    from wand.color import Color
    
    # do some pyplot stuff
    import matplotlib.pyplot as plt
    plt.plot([1, 2, 3, 4])
    
    # Do some wand stuff
    #img = Image(width=850, height=600) # This dimension does not work
    img = Image(width=800, height=600) # This dimension does work
    with Drawing() as drw:
    	drw.fill_color = Color('green')
    	drw.rectangle(left=0,
    				top=0,
    				width=img.width,
    				height=img.height,
    				radius=img.width*0.05)
    	drw(img)
    img.save(filename='output.png')
    

    Thanks for your help!

    seeking-help 
    opened by reisenmachtfreude 1
  • OUTLINE missing pt.2(seeking help)

    OUTLINE missing pt.2(seeking help)

    Ref: https://github.com/emcconville/wand/issues/564

    I think the following codes are messing with outline.

    ##########   main func for image rendering   ##############
    
    def export_caption(caption, filename):
        '''Creates a .png file <filename> suitable for bdsup2sub that displays
        the given caption.'''
        img = Image(width=XSIZE, height=YSIZE)
        # by default wand will use the text's baseline as y-coord which is bad,
        # because we'd never know where we end, so set the gravity to north_west
        # Beware: it seems like if we set text_alignment='center' so we could
        # use wand's multiline text feature the gravity setting will be lost
        # irrevocably, so we need to deal with multiline captions ourselves
        img.gravity = 'north_west'
        box = Drawing()
        # Color() handles 'none' by itself, case-independently
        box.fill_color = Color(OPTS.BOXCOLOR)
    
        draw = Drawing()
        draw.fill_color = Color(OPTS.FILLCOLOR)
        draw.font = FONT
        draw.font_size = FONTSIZE
        draw.text_encoding = ENCODING
        if OPTS.ANTIALIASING:
            draw.text_antialias = True
        else:
            draw.text_antialias = False
        if OUTLINEWIDTH:
            draw.stroke_color = "BLACK"
            draw.stroke_width = OUTLINEWIDTH
            if OPTS.ANTIALIASING:
                draw.stroke_antialias = True
            else:
                draw.stroke_antialias = False
    
        lines = [line.strip() for line in caption.splitlines() if line.strip()]
    
        # padding for the text's bounding box
        padx, pady = BOXPADDING
    
        # calculate the max. allowed text width, and don't forget the outline but
        # ignore the box; keep a few extra px. (1% of XSIZE) in reserve,
        # just to be on the safe side in case we have rounding errors
        max_textwidth = int(round(XSIZE * MAXLINESIZE / 100)) - \
                        2 * OUTLINEWIDTH - int(round(0.01 * XSIZE))
    
        # now loop through the list of strings, calculate each string's width and
        # if necessary split it in two;
        # repeat this until no line needs to be wrapped
        lines, wmax, line_widths = fix_caption(lines, max_textwidth, img, draw)
    
        # collect info for which lines we need y box padding;
        # this seems useful to avoid a too big offset between text lines,
        # which may look odd, esp. when the box is transparent
        i = 0
        padinfo = []
        for lw in line_widths:
            a, b, c = 0, 0, 0 # top padding, bottom padding, Y incr. of next line
            if i == 0:
                # the first line needs top padding
                a = pady
            elif line_widths[i-1] < lw:
                # previous line is smaller, so we need top padding
                a = pady
            if i == len(line_widths) - 1:
                # the last line needs bottom padding
                b = pady
            elif line_widths[i+1] < lw:
                # next line is smaller, so we need bottom padding
                b = pady
            elif line_widths[i+1] > lw:
                # next line is bigger, shift the Y-increment by pady
                c = pady
            i += 1
            padinfo.append((a, b, c))
    
        # width of the box == max. textwidth + 2* (boxpad + outline width)
        wmax = wmax + 2*padx + 2*OUTLINEWIDTH
    
        # now all lines should be safe to fit on the screen,
        # so start drawing
        Y = 0
        i = 0
        bottom = 0
        for line in lines:
            s = line.strip()
            m = draw.get_font_metrics(img, line)
            w, h = int(m.text_width), int(m.text_height)
    
            # make sure the smaller line appears centered relative to the
            # bigger line
            if wmax > XSIZE:
                # may happen if an insane x box padding was given;
                # make sure the text will be centered anyway, the excess box
                # will be chopped off later
                X = int((XSIZE - w) / 2)
            else:
                X = int((wmax - w) / 2)
    
            a, b, c = padinfo[i]
            # draw the bounding box
            if OPTS.BOXCOLOR.lower() != 'none':
                box.rectangle(X - OUTLINEWIDTH - padx,
                              Y - OUTLINEWIDTH - a,
                              X + w + OUTLINEWIDTH + padx,
                              Y + h + OUTLINEWIDTH + b)
                box(img)
    
            # draw the text and shift the Y position to the correct
            # coordinate for the following line (if any)
            draw.text(X, Y, s)
            draw(img)
    
            # store bottom Y coord
            bottom = Y + h + OUTLINEWIDTH + b
            Y = bottom + c + OUTLINEWIDTH + 2 # 1 px. extra so the boxes won't overlap
            i += 1
    
        x0, y0, x1, y1 = 0, 0, wmax + 1, bottom + 1
        # cut the text box from the surrounding void
        if y1 > YSIZE:
            # may happen if the font is too big or an insane y boxpadding is set
            printerror('\nError: generated subtitle image exceeds screen height')
            printerror('The offending subtitle text was:')
            for line in caption.splitlines():
                printerror('    ' + line)
            printerror('This subtitle will not look as expected.')
            y1 = YSIZE
    
        if x1 > XSIZE:
            # may happen if the user set insane boxpadding values, making
            # it impossible to wrap the text to fit into one line
            printerror('\nError: generated subtitle image exceeds screen width')
            printerror('The offending subtitle text was:')
            for line in caption.splitlines():
                printerror('    ' + line)
            printerror('This subtitle may not look as expected.')
            x1 = XSIZE
    
        img.crop(x0, y0, x1, y1)
    
        # write file and return the size for our xml content
        img.format = 'png'
        img.save(filename=filename)
        box.destroy()
        draw.destroy()
        img.destroy()
        return wmax+1, bottom+1
    
    

    Whole file: srt2vobsub.zip

    opened by OilSubjectLoss7 0
  • Deskew method errors out when running in docker(linux)

    Deskew method errors out when running in docker(linux)

    I am ending up with an error when I use the below code when its run in docker.

    try:
         with skew(blob=img_png) as img_png_1:           
             img_png_1.deskew(0.5 * img_png_1.quantum_range)
             pil_image = Image.open(io.BytesIO(img_png_1.make_blob("png")))            
             img_png = image_to_byte_array(pil_image)            
         log.info("Corrected the Skewness for %s", file_name)
     except Exception as e:
         log.exception(f'Exception:{e} occured while Corrected the Skewness for {file_name}')
         pass
    

    Error Message: wand.exceptions.WandRuntimeError: MagickReadImage returns false, but did not raise ImageMagick exception. This can occur when a delegate is missing, or returns EXIT_SUCCESS without generating a raster.

    When I run this in local windows, I don't see any error, but failed in docker(linux). It keeps working for few images and fails for few. Please advice.

    seeking-help 
    opened by uday-felix 4
  • Importing wand takes 700ms on Ubuntu (and can't be avoided via environment)

    Importing wand takes 700ms on Ubuntu (and can't be avoided via environment)

    In Ubuntu 18.04 LTS, the libmagickwand-6.q16-3 package installs the wand libraries at:

    • /usr/lib/x86_64-linux-gnu/libMagickCore-6.Q16.so.3
    • /usr/lib/x86_64-linux-gnu/libMagickWand-6.Q16.so.3

    import wand finds these, but it takes ~700ms to do because it runs ctypes.find_library (apparently several times?)

    Looking at the source code, it seemed like we could avoid this by setting MAGICK_HOME and WAND_MAGICK_LIBRARY_SUFFIX in our containers.

    However, this doesn't actually help because wand hardcodes the .so extension, and .so.3 doesn't match.

    Perhaps wand should handle a couple of environment variables containing the full paths to the libraries?

    opened by craigds 4
  • Wand silently crashes if hugging face transformers library is imported immediately before Wand import

    Wand silently crashes if hugging face transformers library is imported immediately before Wand import

    The following code behaves as expected:

    from wand.image import Image # MUST BE RUN BEFORE `from transformers import ... ` or will produce silent failure
    from transformers import PreTrainedTokenizer # MUST BE RUN AFTER `from wand.image import... ` or will produce silent failure
    
    with Image(filename='/path/to/filename.pdf') as wand_img:
        for page in wand_img.sequence:
            page_img = Image(page)
            print('foo')
    

    However, if the libraries are imported in the opposite order, Wand will silently terminate on line 6:

    from transformers import PreTrainedTokenizer # MUST BE RUN AFTER `from wand.image import... ` or will produce silent failure
    from wand.image import Image # MUST BE RUN BEFORE `from transformers import ... ` or will produce silent failure
    
    with Image(filename='/path/to/filename.pdf') as wand_img:
        for page in wand_img.sequence:
            page_img = Image(page) # crashes
            print('foo')
    

    transformers version 4.6.1 Wand version 0.6.6

    opened by matoles 5
Releases(0.6.10)
Owner
Eric McConville
Lead Software Engineer focusing on web applications, system architecture, content delivery, and resource management.
Eric McConville
Gbs-image-colorizer - A tool to convert colorful pictures to GB Studio-compatible colorized backgrounds.

GB Studio Image Colorizer A tool to convert colorful pictures to GB Studio-compatible colorized backgrounds. Made by NalaFala/Yousurname/Y0UR-U5ERNAME

Yousurname 8 Dec 08, 2022
EmbedToolV2 - 2.0 Version of DraKenCodeZ/ImageEmbedTool

EmbedToolV2 - 2.0 Version of DraKenCodeZ/ImageEmbedTool

DraKenCodeZ 1 Dec 07, 2021
Ascify-Art - An easy to use, GUI based and user-friendly colored ASCII art generator from images!

Ascify-Art This is a python based colored ASCII art generator for free! How to Install? You can download and use the python version if you want, modul

Akash Bora 14 Dec 31, 2022
Pythonocc nodes for Ryven

Pythonocc-nodes-for-Ryven Pythonocc nodes for Ryven Here a way to work on Pythonocc with a node editor, Ryven in that case. To get it functional you w

Tanneguy 30 Dec 18, 2022
Depix is a tool for recovering passwords from pixelized screenshots.

This implementation works on pixelized images that were created with a linear box filter. In this article I cover background information on pixelization and similar research.

23.1k Jan 04, 2023
Fuzzware is a project for automated, self-configuring fuzzing of firmware images

Fuzzware Fuzzware is a project for automated, self-configuring fuzzing of firmware images. The idea of this project is to configure the memory ranges

190 Dec 21, 2022
PyLibTiff - a wrapper to the libtiff library to Python using ctypes

PyLibTiff is a package that provides: a wrapper to the libtiff library to Python using ctypes. a pure Python module for reading and writing TIFF and L

Pearu Peterson 105 Dec 21, 2022
Typesheet is a tiny Python script for creating transparent PNG spritesheets from TrueType (.ttf) fonts.

typesheet typesheet is a tiny Python script for creating transparent PNG spritesheets from TrueType (.ttf) fonts. I made it because I couldn't find an

Grayson Chao 12 Dec 23, 2022
Quickly 'anonymize' all people in an image. This script will put a black bar over all eye-pairs in an image

Face-Detacher Quickly 'anonymize' all people in an image. This script will put a black bar over all eye-pairs in an image This is a small python scrip

Don Cato 1 Oct 29, 2021
A Toolbox for Image Feature Matching and Evaluations

This is a toolbox repository to help evaluate various methods that perform image matching from a pair of images.

Qunjie Zhou 342 Dec 29, 2022
Qrgenerator - A qr generator app using python3

qrgenerator by Mal4D Hi welcome into qr code generator using python by Mal4d Lin

Mal4D 1 Jan 09, 2022
Fast Image Retrieval (FIRe) is an open source image retrieval project

Fast Image Retrieval (FIRe) is an open source image retrieval project release by Center of Image and Signal Processing Lab (CISiP Lab), Universiti Malaya. This project implements most of the major bi

CISiP Lab 39 Nov 25, 2022
Sombra is simple Raytracer written in pure Python.

Sombra Sombra is simple Raytracer written in pure Python. It's main purpose is to help understand how raytracing works with a clean code. If you are l

Hernaldo Jesus Henriquez Nuñez 10 Jul 16, 2022
Music Thumbnail Maker

Music Thumbnail Installing pip install TMFrame

krypton 4 Jan 28, 2022
:rocket: A minimalist comic reader

Pynocchio A minimalist comic reader Features | Installation | Contributing | Credits This screenshots contains a page of the webcomic Pepper&Carrot by

Michell Stuttgart 73 Aug 02, 2022
Image Reading, Metadata Conversion, and Image Writing for Microscopy Images in Python

AICSImageIO Image Reading, Metadata Conversion, and Image Writing for Microscopy Images in Pure Python Features Supports reading metadata and imaging

Allen Institute for Cell Science - Modeling 137 Dec 14, 2022
An executor that wraps 3D mesh models and encodes 3D content documents to d-dimension vector.

3D Mesh Encoder An Executor that receives Documents containing point sets data in its blob attribute, with shape (N, 3) and encodes it to embeddings o

Jina AI 11 Dec 14, 2022
Python script to generate vector graphics of an oriented lattice unit cell

unitcell Python script to generate vector graphics of an oriented lattice unit cell Examples unitcell --type hexagonal --eulers 12 23 34 --axes --crys

Philip Eisenlohr 2 Dec 10, 2021
Design custom QR codes with this web app!

My-QR.Art This web app lets users design their own QR codes to any domain. It can be acessed on my-qr.art. You can find some more background info abou

Marien Raat 406 Dec 20, 2022
ProsePainter combines direct digital painting with real-time guided machine-learning based image optimization.

ProsePainter Create images by painting with words. ProsePainter combines direct digital painting with real-time guided machine-learning based image op

Morphogen 276 Dec 17, 2022