Wand is a 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/wtDWDE9fXK
Stack Overflow tag (Q&A)
http://stackoverflow.com/questions/tagged/wand
Continuous Integration (Travis CI)

https://app.travis-ci.com/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
A simple python script to reveal the contents of a proof of vaccination QR code.

vaxidecoder A simple python script to reveal the contents of a proof of vaccination QR code. It takes a QR code image as input, and returns JSon data.

Hafidh 2 Feb 28, 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
👾 Python project to help you convert any image into a pixel art.

👾 Pixel Art Generator Python project to help you convert any image into a pixel art. ⚙️ Developer's Guide Things you need to get started with this co

Atul Anand 6 Dec 14, 2022
An API which would colorize a black and white image

Image Colorization API Machine Learning Model used- https://github.com/richzhang/colorization/tree/caffe Paper - https://arxiv.org/abs/1603.08511 Step

Neelesh Ranjan Jha 4 Nov 23, 2021
This Web App lets you convert your Normal Image to a SKETCHED one within a minute

This Web App lets you convert your Normal Image to a SKETCHED one within a minute

Avinash M 25 Nov 10, 2022
ImageStrike是一款用于CTF中图片隐写的综合利用工具

🎈 简介 ImageStrike是一款使用PyQT5开发,用于CTF中图片隐写的综合利用工具

zR00t1 133 Dec 27, 2022
💯 Watermark your images with one line of command

Watermarker 💯 Watermark your images with one line of command 🧐 $ pip3 install

Orhan Emre Dikicigil 3 May 01, 2022
A little Python tool to convert a TrueType (ttf/otf) font into a PNG for use in demos.

font2png A little Python tool to convert a TrueType (ttf/otf) font into a PNG for use in demos. To use from command line it expects python3 to be at /

Rich Elmes 3 Dec 22, 2021
Fixes 500+ mislabeled MURA images

In this repository, new csv files are provided that fixes 500+ mislabeled MURA x-rays for all categories. The mislabeled x-rays mainly had hardware in them. This project only fixes the false negative

Pieter Zeilstra 4 May 18, 2022
Panel Competition Image Generator

Panel Competition Image Generator This project was build by a member of the NFH community and is open for everyone who wants to try it. Relevant links

Juliano Mendieta 1 Oct 22, 2021
Bot by image recognition simulating (random) human clicks

bbbot22 bot por reconhecimento de imagem simulando cliques humanos (aleatórios) inb4: sim, esse é basicamente o mesmo bot de 2021 porque a Globo não t

Yuri 2 Apr 05, 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
Python modules to work with large multiresolution images.

Large Image Python modules to work with large, multiresolution images. Large Image is developed and maintained by the Data & Analytics group at Kitwar

Girder 136 Jan 02, 2023
A small Python module for BMP image processing.

micropython-microbmp A small Python module for BMP image processing. It supports BMP image of 1/2/4/8/24-bit colour depth. Loading supports compressio

Quan Lin 4 Nov 02, 2022
A tool to maintain an archive/mirror of your Google Photos library for backup purposes.

Google Photos Archiver Updated Instructions 8/9/2021 Version 2.0.6 Instructions: Download the script (exe or python script listed below) Follow the in

Nick Dawson 116 Jan 03, 2023
Instagram-like image filters.

PyGram Instagram-like image filters. Usage First, import the client: from filters import * Instanciate a filter and apply it: f = Nashville("image.jp

Ajay Kumar Nagaraj 0 Oct 18, 2022
A python based library to help you create unique generative images based on Rarity for your next NFT Project

Generative-NFT Generate Unique Images based on Rarity A python based library to help you create unique generative images based on Rarity for your next

Kartikay Bhutani 8 Sep 21, 2022
This tool allows the user to convert a 16 by 16 image into a list with numbers representing an object/character.

Room Formatter This tool allows the user to convert a 16 by 16 image into a list with numbers representing an object/character. There is cur

Thomas Landstra 1 Nov 13, 2021
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
An API that renders HTML/CSS content to PNG using Chromium

html_png An API that renders HTML/CSS content to PNG using Chromium Disclaimer I am not responsible if you happen to make your own instance of this AP

10 Aug 08, 2022