B
    |bVY             R   @   sb  d Z ddlZddlZddlZddlZddlmZ ddlmZm	Z	m
Z
 ddlmZ ddlmZmZmZmZmZmZmZmZmZ ddlmZmZmZmZ dd	lmZ dd
lmZm Z  ddl!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z' ddl(m)Z)m*Z* dZ+dZ,e)dkrdZ,dZ-e.dddddddddddddddddddddZ/e)dkrhe.dddddddddddddddddddddd dd!Z/d"Z0e)dkrzd#Z0d$Z1e)dkrd%Z1d&Z2d'Z3e)dkrd(Z3d)Z4e)dkrd*Z4d+Z5d,Z6d-Z7d.Z8e)dkrd/Z8d0Z9d1Z:e)dkrd2Z:d3Z;d4Z<d5Z=e)dkrd6Z=d7Z>d8Z?e)dkrd9Z?d:Z@e)dkr*d;Z@d<ZAeBd=d>d?d@dAdBdCdDdEdFdGdHdIdJdKdLdMdNdOdPdQdRdSdTdUdVgZCdWZDdXdYdZd[d\d]d^d_d`dadbdcdddedfdgdgdhdidjdkdldmd]dndodpdqdrdsdtdudvdwdxdydzd{d|d}d~dddddddddddddddddddddddddddddddddddddddd`dQZEdZFdZGe.ddddddddZHdZIe)dkrFdZIdZJdZKdZLe)dkr`dZLdd ZMdd ZNG dd de ZOG dd deOZPG dd de ejQZQG dd deRZSG dd deSejTZUG dd deSejTZVG dd deSejTZWG dd deSejTZXG ddĄ deSejYZZG ddƄ deSejYZ[G ddȄ dejYZ\G ddʄ deRZ]G dd̄ deZ^dS )ah  :mod:`wand.image` --- Image objects
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Opens and manipulates images. Image objects can be used in :keyword:`with`
statement, and these resources will be automatically managed (even if any
error happened)::

    with Image(filename='pikachu.png') as i:
        print('width =', i.width)
        print('height =', i.height)

    N   )
assertions)libc	libmagicklibrary)Color)	abcbinarybinary_typeencode_filename
file_typesstring_typetextto_bytesxrange)MissingDelegateErrorWandExceptionWandRuntimeErrorWandLibraryVersionError)Font)DestroyedResourceErrorResource)CCObjectInfoCCObjectInfo70AChannelFeatureGeometryInfo	PixelInfoRectangleInfo)MAGICK_VERSION_NUMBERMAGICK_HDRI)+ALPHA_CHANNEL_TYPESAUTO_THRESHOLD_METHODSCHANNELSCOLORSPACE_TYPESCOMPARE_METRICSCOMPOSITE_OPERATORSCOMPRESSION_TYPESDISPOSE_TYPESDISTORTION_METHODSDITHER_METHODSEVALUATE_OPSFILTER_TYPESFUNCTION_TYPESGRAVITY_TYPESIMAGE_LAYER_METHODIMAGE_TYPESINTERLACE_TYPESKERNEL_INFO_TYPESMORPHOLOGY_METHODSNOISE_TYPESORIENTATION_TYPESPAPERSIZE_MAPPIXEL_INTERPOLATE_METHODSRENDERING_INTENT_TYPESSPARSE_COLOR_METHODSSTATISTIC_TYPESSTORAGE_TYPESVIRTUAL_PIXEL_METHOD
UNIT_TYPES	BaseImageChannelDepthDictChannelImageDictClosedImageErrorHistogramDictImageImagePropertyIteratorMetadata
OptionDictmanipulativeArtifactTreeProfileDictConnectedComponentObject)	undefinedactivate
backgroundcopy
deactivateextractopaqueresetsetshapetransparentflattenremove	associatedisassociatei   )rK   rL   rX   rM   rN   rO   ZdiscreterY   rP   offonrQ   rW   rS   rT   rU   )rK   kapurZotsutriangle             /   i@         i)rK   redgraycyangreenmagentablueyellowalphaopacityblackindexcomposite_channelsall_channels
true_alphargbrgb_channelsgray_channelssync_channelsdefault_channels         i   )rK   rf   rg   rh   ri   rj   rk   rl   ro   rm   rn   rp   Zreadmask
write_maskmetarq   rr   rs   rt   ru   rv   rw   rx   )"rK   rt   rg   rU   ohtalabxyzycbcryccyiqypbpryuvcmyksrgbhsbhslhwbZ
rec601lumarec601ycbcrZ
rec709lumarec709ycbcrlogcmyluvhcllchlmslchablchuvscrgbhsihsvhclpydbdr)!rK   r   r   rg   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r~   r   r   rt   r   r   rU   Zxyyr   r   r   r   r   r   r   )
rK   absolutemean_absolutemean_error_per_pixelmean_squaredpeak_absolutepeak_signal_to_noise_ratioroot_mean_squarenormalized_cross_correlationfuzz)rK   r   r   r   r   r   r   r   r   Zperceptual_hashr   Zstructural_similarityZstructural_dissimilarity)rK   add	conjugatedivide	magnitudemultiplyZreal_imaginarysubtract)FrK   nomodulus_addatopblendbumpmapchange_maskclear
color_burncolor_dodgecolorize
copy_black	copy_bluerN   	copy_cyan
copy_greencopy_magentaZcopy_opacitycopy_redcopy_yellowdarkendst_atopdstdst_indst_outdst_over
differencedisplacedissolve	exclusion
hard_lighthueinlightenlinear_lightluminize	minus_dstmodulater   outoveroverlayplusreplacesaturatescreen
soft_lightsrc_atopsrcsrc_insrc_outsrc_overmodulus_subtract	thresholdxor
divide_dstdistortblurpegtop_lightvivid_light	pin_lightlinear_dodgelinear_burnmathematics
divide_src	minus_srcdarken_intensitylighten_intensityhard_mixstereo)HrK   rm   r   r   r   r   r   r   r   r   r   r   r   rN   r   r   r   Z
copy_alphar   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   Z	intensityr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   )rK   r   bzipdxt1dxt3dxt5faxgroup4jpegjpeg2000losslessjpeglzwrlezipzipspizpxr24b44b44alzmajbig1jbig2)rK   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   )rK   nonerM   previous)rK   ZaffineZaffine_projectionZscale_rotate_translateZperspectiveZperspective_projectionZbilinear_forwardZbilinear_reverse
polynomialarcZpolarZdepolarZcylinder_2_planeZplane_2_cylinderZbarrelZbarrel_inverseshepardsresizesentinelZrigidaffine)rK   r   	riemersmaZfloyd_steinberg)!rK   r   andr   	leftshiftmaxminr   or
rightshiftrS   r   r   powr   r   thresholdblackthresholdwhitegaussiannoiseimpulsenoiselaplaciannoisemultiplicativenoisepoissonnoiseuniformnoisecosinesine
addmodulusmeanabsexponentialmediansumrootmeansquare)"rK   r  r   r  r  r  r   r  r  r  r  r  r   r	  r  r  r
  r  r   r  r  r  r  r  rS   r  r   r  r  r   r  r  r   Zinverse_log)rK   pointboxr]   ZhermiteZhanningZhammingZblackmangaussianZ	quadraticZcubiccatromZmitchellZjincZsincZsincfastZkaiserZwelshZparzenZbohmanZbartlettZlagrangeZlanczosZlanczossharpZlanczos2Zlanczos2sharpZrobidouxZrobidouxsharpr  spliner  )rK   r  sinusoidarcsinarctan)rK   r%  r&  r  r$  )Zforget
north_westnorth
north_eastwestcentereast
south_westsouth
south_eastZstatic)rK   coalesce
compareanycompareclearcompareoverlaydisposeoptimizeZoptimizeimageZoptimizeplusZoptimizetransZ
removedupsZ
removezero	compositemergerV   mosaic
trimbounds)rK   bilevel	grayscaleZgrayscalemattepaletteZpalettematte	truecolortruecolormattecolorseparationZcolorseparationmatter5  Zpalettebilevelmatte)rK   r:  r;  Zgrayscalealphar<  Zpalettealphar=  truecoloralphar?  Zcolorseparationalphar5  Zpalettebilevelalpha)rK   r   lineZplane	partitionZgifr   png)&rK   unityr!  dogr   r   comet	laplaciansobel	frei_chenrobertsprewittcompasskirschdiamondsquare	rectangleoctagondiskr   crossringpeaksedgescorners	diagonals	line_endsline_junctionsridgesconvex_hullthin_seskeleton	chebyshev	manhattan	octagonal	euclideanuser_definedbinomial)&rK   rD  r!  rE  r   r   rF  rd  rG  rH  rI  rJ  rK  rL  rM  rN  rO  rP  rQ  rR  r   rS  rT  rU  rV  rW  rX  rY  rZ  r[  r\  r]  r^  r_  r`  ra  rb  rc  )rK   convolve	correlateerodedilateerode_intensitydilate_intensitydistanceopencloseopen_intensityclose_intensitysmoothedgeinedgeoutedgetophat
bottom_hathit_and_missthinningthickenvoronoiiterative_distance)rK   re  rf  rg  rh  ri  rj  rz  rl  rm  rn  ro  rp  rq  rr  rs  rt  ru  rv  rw  rx  rk  ry  )rK   uniformr!  Zmultiplicative_gaussianZimpulserG  Zpoissonrandomcaptioncommentzdate:createzdate:modifyzexif:ColorSpacezexif:InteroperabilityIndexfillz
film-gammagammazhdr:exposurezjpeg:colorspacezjpeg:sampling-factorlabelzpdf:use-cropboxzpng:bit-depth-writtenzpng:IHDR.bit-depth-origzpng:IHDR.color-type-origzpng:tIMEzreference-blackzreference-white	signatureztiff:Orientationztiff:photometricztiff:ResolutionUnitztype:hintingzvips:metadata)	rK   top_left	top_rightbottom_rightbottom_leftleft_top	right_topright_bottomleft_bottom)i   i  )ih  i  )i  i  )i@  i  )i  i  )i  i`  )i  i  )i  i  )i  i  )i  iU  )i*  i  )iP	  i*  )i  iP	  )i  i  )iJ  i  )iS  iJ  )i  iS  )i*  i  )   i*  )   r  )i   r  )J   r  )i`  i  )i  i  )i  i 
  )i 
  i  )ih  i  )i  ih  )[      )i  i  )i  i  )i  i  )i  i  )ik  i  )i  ik  )   i  )r  r  )i'
  i\  )i-  i'
  )i  i-  )i  i  )i  i  )i  i  )iC  i  )   iC  )i  i0  )i0  i	  )i	  i`  )i  i  )id  i  )i  id  )i  i  )i  i  )X   }   )i  i  )i  i  )i  i  )i  i  )ib  i  )   ib  )   r  )r  r  )i  i  )i  i  )i  i  )il  i  )i  il  )   i  )rz   r  )i  i  )id  i  )id  i  )i  i  )ib  i  )QZ4x6Z5x7Z7x9Z8x10Z9x11Z9x12Z10x13Z10x14Z11x17Z4A0Z2A0Za0Za1Za2a3Za4Za4smallZa5Za6Za7Za8Za9Za10ZarchaZarchbZarchCZarchdZarcheZb0b1Zb10b2Zb3Zb4Zb5Zb6Zb7Zb8Zb9Zc0c1c2c3Zc4Zc5Zc6Zc7ZcsheetZdsheetZesheetZ	executiveZflsaZflseZfolioZ
halfletterZisob0Zisob1Zisob10Zisob2Zisob3Zisob4Zisob5Zisob6Zisob7Zisob8Zisob9Zjisb0Zjisb1Zjisb2Zjisb3Zjisb4Zjisb5Zjisb6ledgerZlegalletterZlettersmallZmonarchZquartoZ	statementZtabloid)rK   ZaverageZaverage9Z	average16rM   bilinearr   r"  integerZmeshZnearestr#  )rK   
saturationZ
perceptualr   relative         )rK   Zbarycentricr  r  ry  Zinverser`  )
rK   gradientmaximumr  r  minimummodenonpeakstandard_deviationr   )
rK   r  r  r  r  r  r  r  r   r  )rK   chardoublefloatr  longZquantumshort)rK   ZpixelsperinchZpixelspercentimeter)rK   rM   Zconstantditherrs  mirrorr|  tilerU   maskro   rg   whitehorizontal_tilevertical_tilehorizontal_tile_edgevertical_tile_edgechecker_tile)rK   rM   r  rs  r  r|  r  rU   r  ro   rg   r  r  r  r  r  r  c                s   t   fdd}|S )zDMark the operation manipulating itself instead of returning new one.c                s    | f||}d| _ |S )NT)dirty)selfargskwargsresult)function M/home/ankuromar296_gmail_com/.local/lib/python3.7/site-packages/wand/image.pywrapped?  s    zmanipulative.<locals>.wrapped)	functoolswraps)r  r  r  )r  r  rG   =  s    rG   c                s   t   fdd}|S )Nc                s$    | f||}t |s |   |S )N)boolraise_exception)r  r  r  r  )r  r  r  r  H  s    ztrap_exception.<locals>.wrapped)r  r  )r  r  r  )r  r  trap_exceptionG  s    r  c            
   @   s  e Zd ZdZdZdZdZdZej	Z
ejZejZejZdZdd Zdd Zdd	 Zd
d Zdd Zdd Zdd Zdd Zd0ddZedd Zedd Zejedd Zedd Z edd Z!e!jed d Z!ed!d" Z"e"jed#d" Z"ed$d% Z#e#jd&d% Z#ed'd( Z$e$jd)d( Z$ed*d+ Z%ed,d- Z&e&jed.d- Z&ed/d0 Z'e'jd1d0 Z'ed2d3 Z(e(jd4d3 Z(ed5d6 Z)e)jed7d6 Z)ed8d9 Z*e*jd:d9 Z*ed;d< Z+e+jed=d< Z+ed>d? Z,e,jd@d? Z,edAdB Z-e-jedCdB Z-edDdE Z.e.jdFdE Z.edGdH Z/e/jedIdH Z/edJdK Z0e0jedLdK Z0edMdN Z1e1jedOdN Z1edPdQ Z2e2jdRdQ Z2edSdT Z3e3jdUdT Z3edVdW Z4e4jedXdW Z4edYdZ Z5e5jd[dZ Z5ed\d] Z6e6jed^d] Z6ed_d` Z7edadb Z8e8jdcdb Z8eddde Z9e9jdfde Z9edgdh Z:edidj Z;edkdl Z<e<jdmdl Z<edndo Z=e=jedpdo Z=edqdr Z>edsdt Z?edudv Z@edwdx ZAeAjedydx ZAedzd{ ZBeBjed|d{ ZBed}d~ ZCeCjedd~ ZCedd ZDeDjedd ZDedd ZEeEjedd ZEedd ZFeFjedd ZFedd ZGedd ZHeHjdd ZHedd ZIeIjdd ZIedd ZJeJjedd ZJedd ZKeKjdd ZKedd ZLeLjdd ZLedd ZMeMjdd ZMedd ZNedd ZOedd ZPedd ZQedd ZReRjdd ZRedd ZSeSjdd ZSedd ZTeTjdd ZTedd ZUeUjedd ZUedd ZVeVjedd ZVedd ZWeWjdd ZWedd ZXeXjdd ZXeXjYdd ZXedd ZZeZjedd ZZedd Z[e[jdd Z[edd Z\ddĄ Z]ddƄ Z^ee_d1ddɄZ`ee_d2dd˄Zaee_d3dd̈́Zbed4ddτZcee_d5dd҄Zdee_ddԄ Zeee_ddք Zfee_dd؄ Zgee_d6ddۄZhee_dd݄ Ziee_d7ddZjee_d8ddZke_d9ddZlee_d:ddZmee_d;ddZned<ddZodd Zpe_dd Zqee_d=ddZree_dd Zse_d>ddZtdd Zuee_d?ddZvee_dd Zwee_d d Zxd@ddZyee_dd Zzee_dAddZ{ee_dBdd	Z|ee_dCddZ}edDddZ~edEddZe_dFddZee_dGddZee_dHddZdd Zee_dIddZee_dJdd ZdKd!d"Zee_dLd#d$Ze_dMd&d'Zee_d(d) Zee_d*d+ Zee_d,d- Zee_d.d/ Zee_dNd0d1Zee_dOd2d3Zee_dPd4d5Zee_d6d7 Zee_d8d9 Zee_dQd:d;Zee_dRd<d=ZdSd@dAZee_dTdBdCZdDdE ZdUdFdGZee_dHdI Zee_dJdK Ze_dVdLdMZee_dWdNdOZee_dXdPdQZedYdRdSZee_dZdTdUZee_d[dVdWZd\dXdYZee_d]dZd[Zee_d^d]d^Zd_d_d`Ze_d`dadbZe_dadddeZe_dbdfdgZdhdi Zdjdk Zdldm Zdndo Zdpdq Zdrds Zdtdu Zdvdw Zee_dcdzd{Zddd}d~Zee_deddZe_dfddZee_dgddZee_dhddZee_diddZee_djddZedkddZee_dlddZee_dd ZdmddZee_dnddZee_dd ZdoddZedpddZee_dqddZee_drddZee_dsddZee_dtddZee_duddZee_dvddZee_dwddZee_dxddZee_dd Zee_dd Zee_dyddZɐdd Zʐdd Zee_dzddZee_dd Zee_d{ddZee_d|ddZee_d}dÐdĄZАd~dŐdƄZee_ddǐdȄZe_ddɐdʄZee_ddːd̄Zee_dd͐d΄ZՐdϐdЄ Z֐dѐd҄ Zee_ddӐdԄZee_ddՐdքZee_ddאd؄Zee_ddِdڄZee_ddېd܄Zee_ddݐdބZee_dddZee_dddZee_dddZee_dddZee_dddZee_dddZee_dddZdddZee_dddZe_dddZee_dddZee_dddZee_dddZee_dddZee_dddZee_dd dZe_dd Zee_dddZee_dd Zee_dd	d
Zee_dddZee_dddZee_dddZee_dd Zee_dddZedd Zee_dd Zee_dd Zee_dddZee_dd Zee_dd d!Zee_dd"d#Zedd$d%Zee_dd&d'Zee_dd(d)Z ee_d*d+ Zee_d,d- Ze_dd.d/ZdS (  r=   a  The abstract base of :class:`Image` (container) and
    :class:`~wand.sequence.SingleImage`.  That means the most of
    operations, defined in this abstract class, are possible for
    both :class:`Image` and :class:`~wand.sequence.SingleImage`.

    .. versionadded:: 0.3.0

    N)Z_wandc             C   s.   || _ t| | _t| | _t| | _d| _d S )NF)wandr?   channel_imagesr>   channel_depthsrF   optionsr  )r  r  r  r  r  __init__|  s
    


zBaseImage.__init__c             C   s   t |t| r| j|jkS dS )NF)
isinstancetyper  )r  otherr  r  r  __eq__  s    zBaseImage.__eq__c       
   
   C   s  t |ts>t |tjr>t|}t|}d|  kr>dksRn td|q|dkr0|\}}t |t}t |t}|r|st||d }n|s|rt||d }n|s||s|t |t	j
rt |t	j
stdt||f |dk r|| j7 }|dk r|| j7 }|| jkrtdn<|| jkr2tdn&|dk rFtdn|dk rXtd	t| }|| ||S Q R X |jd kr|jd kstd
n8|jd kr|jd kr|jd kr|jd kr|  S |  }y||j|j|j|j W n0 tk
r* }	 ztt|	W d d }	~	X Y nX |S | |d  S nt |t	j
r|dk rb|| j7 }n8|| jkrtdt| n|dk rtdt| t| }|| | S Q R X nt |tr| d d |f S tdt| d S )Nr   r^   zindex cannot be {0}-dimensionalzx and y must be integral, not r   zx must be less than widthzy must be less than heightzx cannot be less than 0zy cannot be less than 0z slicing with step is unsupportedz(index must be less than height, but got z(index cannot be less than zero, but got zunsupported index type: )r  r   r   Iterabletuplelen
ValueErrorformatslicenumbersIntegral	TypeErrorreprwidthheight
IndexErroriterseeknextstepstartstopclonecropstr)
r  idxdxyZx_sliceZy_sliceiteratorcloneder  r  r  __getitem__  sz    

















zBaseImage.__getitem__c             C   s  t |trt|}tj|d t |tjs:tdt| t	|}t
|dkrddt
|}t|| j}td}| j\}}|\}}	d\}
}t |tjrt |	tjstd|dk r||7 }|	dk r|	|7 }	||krtd	n|	|krtd
|dkrd}tjd  }|j|d< n|dkrtd}tjd  }|j|d< |j|d< |j|d< |j|d< | jr|d7 }|j|d< nHd}tjd  }|j|d< |j|d< |j|d< | jr|d7 }|j|d< t| j||	|
|||t|}|s|   d S )N)colorz'Expecting list of x,y coordinates, not r^   z&pixel index can not be {0}-dimensionalr  )r   r   zExpecting x & y to be integersr   zx must be less than image widthz y must be less than image heightrg      Ir   r   s   CMYK         Ar_   s   RGB) r  r   r   r   assert_colorr   r  r  r  r  r  r  r  
colorspacer:   rp   sizer  r  ctypesc_doublerf   ri   rk   ro   alpha_channelrm   r   MagickImportImagePixelsr  byrefr  )r  r  r  msgr  s_indexr  r  x1y1Zx2y2channel_mappixelrr  r  r  __setitem__  sn    













zBaseImage.__setitem__c             C   s
   t | jS )N)hashr  )r  r  r  r  __hash__  s    zBaseImage.__hash__c             C   s
   t | dS )N)image)rD   )r  r  r  r  __iter__  s    zBaseImage.__iter__c             C   s   | j S )N)r  )r  r  r  r  __len__  s    zBaseImage.__len__c             C   s
   | |k S )Nr  )r  r  r  r  r  __ne__  s    zBaseImage.__ne__ ({self.width}x{self.height})c             C   sl   t | }d|jt|d|j}t| dd d kr:d|S | j}|sNd|S d||d d |j| dS )	Nz{0}.{1}__qualname__Z
c_resourcez<{0}: (closed)>z<{0}: (empty)>z<{0}: {1}{2}>rd   )r  )r  r  
__module__getattr__name__r  )r  extra_formatclstypenamesigr  r  r  __repr__  s    

zBaseImage.__repr__c             C   s   | j std| j\}}d}| j}|dkr4td}n|dkrFtd}ntd}| jr`|td7 }t|}|| | tj  | _	t
| jd	d	||||t| j	}|s|   tt| j	d
f|||fdddS )ap  Allows image-data from :class:`Image <wand.image.BaseImage>`
        instances to be loaded into numpy's array.

        .. code::

            import numpy
            from wand.image import Image

            with Image(filename='rose:') as img:
                img_data = numpy.asarray(img)

        :raises ValueError: if image has no data.

        .. versionadded:: 0.5.0
        .. versionchanged:: 0.6.0
           The :attr:`shape` property is now ordered by ``height``, ``width``,
           and ``channel``.
        .. versionchanged:: 0.6.2
           Color spaces ``gray`` & ``cmyk`` are now supported.
        z No image data to interface with.r   )rg   R)r   ZCMYKRGBAr   Tz|u1r  )datarT   typestrversion)r  r  r  r  r	   r  r  r  c_charZ	_c_bufferr   MagickExportImagePixelsr  r  r  dict	addressof)r  r  r  Zstorage_typecsZchannel_formatZchannel_numberr  r  r  r  __array_interface__  s0    


zBaseImage.__array_interface__c             C   s   t t| jS )a	  (:class:`bool`) Get state of image alpha channel.
        It can also be used to enable/disable alpha channel, but with different
        behavior such as new, copied, or existing.

        Behavior of setting :attr:`alpha_channel` is defined with the
        following values:

        - ``'activate'``, ``'on'``, or :const:`True` will enable an images
           alpha channel. Existing alpha data is preserved.
        - ``'deactivate'``, ``'off'``, or :const:`False` will disable an images
           alpha channel. Any data on the alpha will be preserved.
        - ``'associate'`` & ``'disassociate'`` toggle alpha channel flag in
           certain image-file specifications.
        - ``'set'`` enables and resets any data in an images alpha channel.
        - ``'opaque'`` enables alpha/matte channel, and forces full opaque
           image.
        - ``'transparent'`` enables alpha/matte channel, and forces full
           transparent image.
        - ``'extract'`` copies data in alpha channel across all other channels,
           and disables alpha channel.
        - ``'copy'`` calculates the gray-scale of RGB channels,
            and applies it to alpha channel.
        - ``'shape'`` is identical to ``'copy'``, but will color the resulting
           image with the value defined with :attr:`background_color`.
        - ``'remove'`` will composite :attr:`background_color` value.
        - ``'background'`` replaces full-transparent color with background
           color.

        .. note::

            The :attr:`alpha_channel` attribute will always return ``True``
            if alpha channel is enabled, and ``False`` otherwise. Setting
            this property with a string value from :const:`ALPHA_CHANNEL_TYPES`
            will resolve to a :class:`bool` after applying channel operations
            listed above.

            With ImageMagick-6, values ``'on'`` & ``'off'`` are aliased to
            ``'activate'`` & ``'deactivate'``. However in ImageMagick-7,
            both ``'on'`` & ``'off'`` have their own behavior.


        .. versionadded:: 0.2.1

        .. versionchanged:: 0.4.1
           Support for additional setting values.
           However :attr:`Image.alpha_channel` will continue to return
           :class:`bool` if the current alpha/matte state is enabled.

        .. versionchanged:: 0.6.0
           Setting the alpha channel will apply the change to all frames
           in the image stack.
        )r  r   ZMagickGetImageAlphaChannelr  )r  r  r  r  r  N  s    6zBaseImage.alpha_channelc             C   s   t dk }|dks|dkr"|r"d}n|dks6|dkr:|r:d}tjtd|d	 t|}t| j t| j}t	| j x2t
d
|d D ] }t| j| t| j| qW d S )Ni   FrZ   rO   Tr[   rL   zwand.image.ALPHA_CHANNEL_TYPES)r  r   r   )r   r   string_in_listr    rp   r   MagickSetLastIteratorr  MagickGetIteratorIndexMagickResetIteratorr   MagickSetIteratorIndexZMagickSetImageAlphaChannel)r  Z
alpha_typeZis_im6Zalpha_indexnir  r  r  r    s    
c             C   s   dS )a  (:class:`bool`) Whether the image is animation or not.
        It doesn't only mean that the image has two or more images (frames),
        but all frames are even the same size.  It's about image format,
        not content.  It's :const:`False` even if :mimetype:`image/ico`
        consits of two or more images of the same size.

        For example, it's :const:`False` for :mimetype:`image/jpeg`,
        :mimetype:`image/gif`, :mimetype:`image/ico`.

        If :mimetype:`image/gif` has two or more frames, it's :const:`True`.
        If :mimetype:`image/gif` has only one frame, it's :const:`False`.

        .. versionadded:: 0.3.0

        .. versionchanged:: 0.3.8
           Became to accept :mimetype:`image/x-gif` as well.

        Fr  )r  r  r  r  	animation  s    zBaseImage.animationc             C   s   t t| jS )z(:class:`bool`) If vectors & fonts will use anti-aliasing.

        .. versionchanged:: 0.5.0
           Previously named :attr:`font_antialias`.
        )r  r   ZMagickGetAntialiasr  )r  r  r  r  	antialias  s    zBaseImage.antialiasc             C   s   t j|d t| j| d S )N)r+  )r   assert_boolr   ZMagickSetAntialiasr  )r  r+  r  r  r  r+    s    c             C   s^   t  }t | jr$t | j|}nt | j}d}|sB|   nt|}t 	|}|S dS )z(:class:`wand.color.Color`) The image background color.
        It can also be set to change the background color.

        .. versionadded:: 0.1.9

        .. versionchanged:: 0.6.7
           Allow property to be set before image read.
        TN)
r   NewPixelWandMagickGetNumberImagesr  ZMagickGetImageBackgroundColorZMagickGetBackgroundColorr  r   from_pixelwandDestroyPixelWand)r  r  r  r  r  r  r  background_color  s    



zBaseImage.background_colorc          	   C   sv   t |trt|}tj|d |J t| jrLt| j|j	}|sL| 
  t| j|j	}|sh| 
  W d Q R X d S )N)r  )r  r   r   r   r  r   r.  r  ZMagickSetImageBackgroundColorresourcer  MagickSetBackgroundColor)r  r  r  r  r  r  r1    s    
c             C   s~   t d}t d}d}d}tdk rBt| j||}|j|jf}n,t d}t| j|||}|j|j|jf}|sz|   |S )z(:class:`tuple`) The chromatic blue primary point for the image.
        With ImageMagick-6 the primary value is ``(x, y)`` coordinates;
        however, ImageMagick-7 has ``(x, y, z)``.

        .. versionadded:: 0.5.2
        g        Ni   )r  r  r   r   ZMagickGetImageBluePrimaryr  valuer  )r  r  r  r  pzr  r  r  blue_primary  s    


zBaseImage.blue_primaryc             C   sf   d }t |tjstdtdk r:|\}}t| j||}n|\}}}t| j|||}|sb|   d S )NzPrimary must be a tuplei   )	r  r   Sequencer  r   r   ZMagickSetImageBluePrimaryr  r  )r  coordinatesr  r  r  r6  r  r  r  r7    s    
c             C   s@   t  }t | j|}|s$|   nt|}t |}|S dS )z(:class:`wand.color.Color`) The image border color. Used for
        special effects like :meth:`polaroid()`.

        .. versionadded:: 0.5.4
        N)r   r-  ZMagickGetImageBorderColorr  r  r   r/  r0  )r  r  r  r  r  r  r  border_color  s    


zBaseImage.border_colorc          	   C   sN   t |trt|}tj|d |" t| j|j}|s@| 	  W d Q R X d S )N)r:  )
r  r   r   r   r  r   ZMagickSetImageBorderColorr  r2  r  )r  r  r  r  r  r  r:    s    
c             C   s   t | jS )z(:class:`numbers.Integral`) Count of unique colors used within the
        image. This is READ ONLY property.

        .. versionadded:: 0.5.3
        )r   ZMagickGetImageColorsr  )r  r  r  r  colors)  s    zBaseImage.colorsc             C   s$   t | j}|s|   tt| S )z(:class:`basestring`) The image colorspace.

        Defines image colorspace as in :const:`COLORSPACE_TYPES` enumeration.

        It may raise :exc:`ValueError` when the colorspace is unknown.

        .. versionadded:: 0.3.4

        )r   ZMagickGetImageColorspacer  r  r#   r   )r  Zcolorspace_type_indexr  r  r  r  2  s    zBaseImage.colorspacec             C   s4   t jtd|d t| jt|}|s0|   d S )Nzwand.image.COLORSPACE_TYPES)r  )r   r#  r#   r   ZMagickSetImageColorspacer  rp   r  )r  colorspace_typer  r  r  r  r  B  s    c             C   s   t | j}t| S )z(:class:`basestring`) The type of image compose.
        It's a string from :const:`COMPOSITE_OPERATORS` list.
        It also can be set.

        .. versionadded:: 0.5.1
        )r   ZMagickGetImageComposer  r%   )r  Zcompose_indexr  r  r  composeO  s    zBaseImage.composec             C   s(   t jtd|d t| jt| d S )Nzwand.image.COMPOSITE_OPERATORS)r=  )r   r#  r%   r   ZMagickSetImageComposer  rp   )r  operatorr  r  r  r=  Z  s
    c             C   s   t | j}t| S )aO  (:class:`basestring`) The type of image compression.
        It's a string from :const:`COMPRESSION_TYPES` list.
        It also can be set.

        .. versionadded:: 0.3.6
        .. versionchanged:: 0.5.2
           Setting :attr:`compression` now sets both `image_info`
           and `images` in the internal image stack.
        )r   ZMagickGetImageCompressionr  r&   )r  Zcompression_indexr  r  r  compressionb  s    zBaseImage.compressionc             C   s<   t jtd|d t| jt| t| jt| d S )Nzwand.image.COMPRESSION_TYPES)r?  )r   r#  r&   r   ZMagickSetCompressionr  rp   ZMagickSetImageCompression)r  r4  r  r  r  r?  p  s    c             C   s   t | jS )a	  (:class:`numbers.Integral`) Compression quality of this image.

        .. versionadded:: 0.2.0
        .. versionchanged:: 0.5.2
           Setting :attr:`compression_quality` now sets both `image_info`
           and `images` in the internal image stack.
        )r   Z MagickGetImageCompressionQualityr  )r  r  r  r  compression_quality~  s    	zBaseImage.compression_qualityc             C   s@   t j|d t| j| t| j|}|s<tdt| dS )zSet compression quality for the image.

        :param quality: new compression quality setting
        :type quality: :class:`numbers.Integral`

        )r@  z%Unable to set compression quality to N)r   assert_integerr   ZMagickSetCompressionQualityr  Z MagickSetImageCompressionQualityr  r  )r  Zqualityr  r  r  r  r@    s    	c             C   s   t | jS )zi(:class:`numbers.Integral`) The number of ticks between frames.

        .. versionadded:: 0.5.9
        )r   ZMagickGetImageDelayr  )r  r  r  r  delay  s    zBaseImage.delayc             C   s   t j|d t| j| d S )N)rB  )r   rA  r   ZMagickSetImageDelayr  )r  r4  r  r  r  rB    s    c             C   s   t | jS )z_(:class:`numbers.Integral`) The depth of this image.

        .. versionadded:: 0.2.1

        )r   MagickGetImageDepthr  )r  r  r  r  depth  s    zBaseImage.depthc             C   s   t | j|}|s|  d S )N)r   MagickSetImageDepthr  r  )r  rD  r  r  r  r  rD    s    c             C   s2   t | j}yt| S  tk
r,   td S X dS )at  (:class:`basestring`) Controls how the image data is
        handled during animations. Values are from :const:`DISPOSE_TYPES`
        list, and can also be set.

        .. seealso::

            `Dispose Images`__ section in ``Animation Basics`` article.

        __ https://www.imagemagick.org/Usage/anim_basics/#dispose_images

        .. versionadded:: 0.5.0
        r   N)r   ZMagickGetImageDisposer  r'   r  )r  Zdispose_idxr  r  r  r4    s
    zBaseImage.disposec             C   s(   t jtd|d t| jt| d S )Nzwand.image.DISPOSE_TYPES)r4  )r   r#  r'   r   ZMagickSetImageDisposer  rp   )r  r4  r  r  r  r4    s    c             C   s.   | j s
dS tt| j | j| j| j| j| jdS )z3(:class:`wand.font.Font`) The current font options.N)pathr  r  r+  stroke_colorstroke_width)	font_pathr   r   	font_size
font_colorr+  rG  rH  )r  r  r  r  font  s    zBaseImage.fontc             C   s^   t |tstdt| |j| _|j| _|j| _	|j
| _
|jrH|j| _|jd k	rZ|j| _d S )Nz#font must be a wand.font.Font, not )r  r   r  r  rF  rI  r  rJ  r  rK  r+  rG  rH  )r  rL  r  r  r  rL    s    

c             C   s   | j S )zQ
        .. deprecated:: 0.5.0
           Use :attr:`antialias` instead.
        )r+  )r  r  r  r  font_antialias  s    zBaseImage.font_antialiasc             C   s
   || _ d S )N)r+  )r  r+  r  r  r  rM    s    c             C   s   t | jd S )Nr  )r   r  )r  r  r  r  rK    s    zBaseImage.font_colorc             C   s.   t |trt|}tj|d |j| jd< d S )N)rK  r  )r  r   r   r   r  stringr  )r  r  r  r  r  rK    s    
c             C   s0   d}t | j}|r,tt|}t |}|S )zY(:class:`basestring`) The path of the current font.
        It also can be set.

        N)r   ZMagickGetFontr  r   r  	string_atMagickRelinquishMemory)r  Zfont_strZfont_pr  r  r  rI    s    
zBaseImage.font_pathc             C   s&   t |}t| j|}|s"|   d S )N)r	   r   ZMagickSetFontr  r  )r  rL  r  r  r  r  rI    s    c             C   s   t | jS )z;(:class:`numbers.Real`) The font size.  It also can be set.)r   ZMagickGetPointsizer  )r  r  r  r  rJ    s    zBaseImage.font_sizec             C   sB   t j|d |dk r$tdt| t| j|}|s>|   d S )N)rJ  g        z!cannot be less than 0.0, but got )r   assert_realr  r  r   ZMagickSetPointsizer  r  )r  r  r  r  r  r  rJ    s    c             C   s0   d}t | j}|r,tt|}t |}|S )a  (:class:`basestring`) The image format.

        If you want to convert the image format, just reset this property::

            assert isinstance(img, wand.image.Image)
            img.format = 'png'

        It may raise :exc:`ValueError` when the format is unsupported.

        .. seealso::

           `ImageMagick Image Formats`__
              ImageMagick uses an ASCII string known as *magick* (e.g. ``GIF``)
              to identify file formats, algorithms acting as formats,
              built-in patterns, and embedded profile types.

           __ http://www.imagemagick.org/script/formats.php

        .. versionadded:: 0.1.6

        N)r   ZMagickGetImageFormatr  r   r  rO  rP  )r  Zfmt_strZfmt_pr  r  r  r  )  s    
zBaseImage.formatc             C   sh   t j|d | }t| jt| }|s>tt	|d t
| jdt|  }|sd|   d S )N)r  z is unsupported formats   buffer.)r   assert_stringstripr   MagickSetImageFormatr  r	   upperr  r  MagickSetFilenamelowerr  )r  fmtr  r  r  r  r  G  s    c             C   s   t | jS )z(:class:`numbers.Real`) The normalized real number between ``0.0``
        and :attr:`quantum_range`. This property influences the accuracy of
        :meth:`compare()`.

        .. versionadded:: 0.5.3
        )r   ZMagickGetImageFuzzr  )r  r  r  r  r   S  s    zBaseImage.fuzzc             C   s   t j|d t| j| d S )N)r   )r   rQ  r   ZMagickSetImageFuzzr  )r  r4  r  r  r  r   ]  s    c             C   s    t | j}|s|   t| S )z(:class:`basestring`) The text placement gravity used when
        annotating with text.  It's a string from :const:`GRAVITY_TYPES`
        list.  It also can be set.

        )r   ZMagickGetGravityr  r  r-   )r  Zgravity_indexr  r  r  gravityb  s    zBaseImage.gravityc             C   s(   t jtd|d t| jt| d S )Nzwand.image.GRAVITY_TYPES)rY  )r   r#  r-   r   ZMagickSetGravityr  rp   )r  r4  r  r  r  rY  n  s    c             C   s~   t d}t d}d}d}tdk rBt| j||}|j|jf}n,t d}t| j|||}|j|j|jf}|sz|   |S )z(:class:`tuple`) The chromatic green primary point for the image.
        With ImageMagick-6 the primary value is ``(x, y)`` coordinates;
        however, ImageMagick-7 has ``(x, y, z)``.

        .. versionadded:: 0.5.2
        g        Ni   )r  r  r   r   ZMagickGetImageGreenPrimaryr  r4  r  )r  r  r  r  r5  r6  r  r  r  green_primaryv  s    


zBaseImage.green_primaryc             C   sf   d }t |tjstdtdk r:|\}}t| j||}n|\}}}t| j|||}|sb|   d S )NzPrimary must be a tuplei   )	r  r   r8  r  r   r   ZMagickSetImageGreenPrimaryr  r  )r  r9  r  r  r  r6  r  r  r  rZ    s    
c             C   s   t | jS )z5(:class:`numbers.Integral`) The height of this image.)r   ZMagickGetImageHeightr  )r  r  r  r  r    s    zBaseImage.heightc             C   s"   t j|d t| j| j| d S )N)r  )r   assert_unsigned_integerr   MagickSetSizer  r  )r  r  r  r  r  r    s    c             C   s   t | S )ab  (:class:`HistogramDict`) The mapping that represents the histogram.
        Keys are :class:`~wand.color.Color` objects, and values are
        the number of pixels.

        .. tip::

            True-color photos can have millions of color values. If performance
            is more valuable than accuracy, remember to :meth:`quantize` the
            image before generating a :class:`HistogramDict`.

                with Image(filename='hd_photo.jpg') as img:
                    img.quantize(255, 'RGB', 0, False, False)
                    hist = img.histogram

        .. versionadded:: 0.3.0

        )rA   )r  r  r  r  	histogram  s    zBaseImage.histogramc             C   s   t | j}t| S )a5  (:class:`basestring`) The interlace used by the image.
        See :const:`INTERLACE_TYPES`.

        .. versionadded:: 0.5.2

        .. versionchanged:: 0.6.2
           The :attr:`interlace_scheme` property now points to the image.
           Previously was pointing to the :c:struct:`MagickWand`.
        )r   ZMagickGetImageInterlaceSchemer  r0   )r  
scheme_idxr  r  r  interlace_scheme  s    zBaseImage.interlace_schemec             C   s,   t jtd|d t|}t| j| d S )Nzwand.image.INTERLACE_TYPES)r_  )r   r#  r0   rp   r   ZMagickSetImageInterlaceSchemer  )r  schemer^  r  r  r  r_    s
    
c             C   s   t | j}t| S )z(:class:`basestring`) The interpolation method of the image.
        See :const:`PIXEL_INTERPOLATE_METHODS`.

        .. versionadded:: 0.5.2
        )r   ZMagickGetImageInterpolateMethodr  r6   )r  
method_idxr  r  r  interpolate_method  s    zBaseImage.interpolate_methodc             C   s,   t jtd|d t|}t| j| d S )Nz$wand.image.PIXEL_INTERPOLATE_METHODS)rb  )r   r#  r6   rp   r   ZMagickSetImageInterpolateMethodr  )r  methodra  r  r  r  rb    s
    
c             C   s   |   \}}|S )z(:class:`numbers.Real`) The kurtosis of the image.

        .. tip::

            If you want both :attr:`kurtosis` & :attr:`skewness`, it
            would be faster to call :meth:`kurtosis_channel()` directly.

        .. versionadded:: 0.5.3
        )kurtosis_channel)r  k_r  r  r  kurtosis  s    zBaseImage.kurtosisc             C   s$   t d}t| jt | |jS )z(:class:`numbers.Integral`) The original size, in bytes,
        of the image read. This will return `0` if the image was modified in
        a way that would invalidate the original length value.

        .. versionadded:: 0.5.4
        r   )r  c_size_tr   ZMagickGetImageLengthr  r  r4  )r  Zsize_ptrr  r  r  length_of_bytes  s    
zBaseImage.length_of_bytesc             C   s   t | jS )zc(:class:`numbers.Integral`) Number of frame iterations.
        A value of ``0`` will loop forever.)r   ZMagickGetImageIterationsr  )r  r  r  r  loop  s    zBaseImage.loopc             C   s   t j|d t| j| d S )N)rj  )r   r[  r   ZMagickSetImageIterationsr  )r  
iterationsr  r  r  rj    s    c             C   s>   t  }t | j|}|r2t|}t |}|S |   dS )z(:class:`wand.color.Color`) The color value of the matte channel.
        This can also be set.

        .. versionadded:: 0.4.1
        N)r   r-  ZMagickGetImageMatteColorr  r   r/  r0  r  )r  r  r  r  r  r  r  matte_color  s    

zBaseImage.matte_colorc          	   C   sN   t |trt|}tj|d |" t| j|j}|s@| 	  W d Q R X d S )N)rl  )
r  r   r   r   r  r   ZMagickSetImageMatteColorr  r2  r  )r  r  r  r  r  r  rl    s    
c             C   s   |   \}}|S )a;  (:class:`numbers.Real`) The maximum quantum value within the image.
        Value between 0.0 and :attr:`quantum_range`

        .. tip::

            If you want both :attr:`maxima` & :attr:`minima`,
            it would be faster to call :meth:`range_channel()` directly.

        .. versionadded:: 0.5.3
        )range_channel)r  rf  Zmax_qr  r  r  maxima$  s    zBaseImage.maximac             C   s   |   \}}|S )a:  (:class:`numbers.Real`) The mean of the image, and have a value
        between 0.0 and :attr:`quantum_range`

        .. tip::

            If you want both :attr:`mean` & :attr:`standard_deviation`, it
            would be faster to call :meth:`mean_channel()` directly.

        .. versionadded:: 0.5.3
        )mean_channel)r  mrf  r  r  r  r  3  s    zBaseImage.meanc             C   s   |   \}}|S )a;  (:class:`numbers.Real`) The minimum quantum value within the image.
        Value between 0.0 and :attr:`quantum_range`

        .. tip::

            If you want both :attr:`maxima` & :attr:`minima`,
            it would be faster to call :meth:`range_channel()` directly.

        .. versionadded:: 0.5.3
        )rm  )r  Zmin_qrf  r  r  r  minimaB  s    zBaseImage.minimac             C   s2   t | j}yt| S  tk
r,   td S X dS )z(:class:`basestring`) The image orientation.  It's a string from
        :const:`ORIENTATION_TYPES` list.  It also can be set.

        .. versionadded:: 0.3.0

        r   N)r   ZMagickGetImageOrientationr  r4   r  )r  Zorientation_indexr  r  r  orientationQ  s
    zBaseImage.orientationc             C   s,   t jtd|d t|}t| j| d S )Nzwand.image.ORIENTATION_TYPES)rr  )r   r#  r4   rp   r   ZMagickSetImageOrientationr  )r  r4  rp   r  r  r  rr  _  s
    
c             C   sd   t  }t  }t  }t  }t| j||||}|s@|   t|jt|jt|jt|jfS )a  The dimensions and offset of this Wand's page as a 4-tuple:
        ``(width, height, x, y)``.

        .. code::

            with Image(filename='wizard:') as img:
                img.page = (595, 842, 0, 0)

        Note that since it is based on the virtual canvas, it may not equal the
        dimensions of an image. See the ImageMagick documentation on the
        virtual canvas for more information.

        This attribute can also be set by using a named papersize. For
        example::

            with Image(filename='wizard:') as img:
                img.page = 'a4'

        .. versionadded:: 0.4.3

        .. versionchanged:: 0.6.4
           Added support for setting by papersize.
        )	r  rh  	c_ssize_tr   ZMagickGetImagePager  r  intr4  )r  whr  r  r  r  r  r  pageh  s    zBaseImage.pagec       	      C   s   t |tr^t| }t }t|tj}t	|t
| |j|j|j|jf}t| ~t |tjrx|\}}}}ntdt| j||||}|s|   d S )Nzpage layout must be 4-tuple)r  r   r   ZGetPageGeometryencoder   r  castc_char_pZParseAbsoluteGeometryr  r  r  r  r  DestroyStringr   r8  r  r   ZMagickSetImagePager  r  )	r  newpageZc_ptrriru  rv  r  r  r  r  r  r  rw    s    

c             C   s
   | j d S )zl(:class:`numbers.Integral`) The height of the page for this wand.

        .. versionadded:: 0.4.3

        r   )rw  )r  r  r  r  page_height  s    zBaseImage.page_heightc             C   s   t | j}||d< || _d S )Nr   )listrw  )r  r  r|  r  r  r  r~    s    
c             C   s
   | j d S )zk(:class:`numbers.Integral`) The width of the page for this wand.

        .. versionadded:: 0.4.3

        r   )rw  )r  r  r  r  
page_width  s    zBaseImage.page_widthc             C   s   t | j}||d< || _d S )Nr   )r  rw  )r  r  r|  r  r  r  r    s    
c             C   s
   | j d S )zn(:class:`numbers.Integral`) The X-offset of the page for this wand.

        .. versionadded:: 0.4.3

        r^   )rw  )r  r  r  r  page_x  s    zBaseImage.page_xc             C   s   t | j}||d< || _d S )Nr^   )r  rw  )r  r  r|  r  r  r  r    s    
c             C   s
   | j d S )zn(:class:`numbers.Integral`) The Y-offset of the page for this wand.

        .. versionadded:: 0.4.3

        r  )rw  )r  r  r  r  page_y  s    zBaseImage.page_yc             C   s   t | j}||d< || _d S )Nr  )r  rw  )r  r  r|  r  r  r  r    s    
c             C   s   t  }tt | |jS )z(`:class:`numbers.Integral`) The maximum value of a color
        channel that is supported by the imagemagick library.

        .. versionadded:: 0.2.0

        )r  rh  r   ZMagickGetQuantumRanger  r4  )r  r  r  r  r  quantum_range  s    zBaseImage.quantum_rangec             C   s~   t d}t d}d}d}tdk rBt| j||}|j|jf}n,t d}t| j|||}|j|j|jf}|sz|   |S )z(:class:`tuple`) The chromatic red primary point for the image.
        With ImageMagick-6 the primary value is ``(x, y)`` coordinates;
        however, ImageMagick-7 has ``(x, y, z)``.

        .. versionadded:: 0.5.2
        g        Ni   )r  r  r   r   ZMagickGetImageRedPrimaryr  r4  r  )r  r  r  r  r5  r6  r  r  r  red_primary  s    


zBaseImage.red_primaryc             C   sf   d }t |tjstdtdk r:|\}}t| j||}n|\}}}t| j|||}|sb|   d S )NzPrimary must be a tuplei   )	r  r   r8  r  r   r   ZMagickSetImageRedPrimaryr  r  )r  r9  r  r  r  r6  r  r  r  r   	  s    
c             C   s   t | j}t| S )z(:class:`basestring`) PNG rendering intent. See
        :const:`RENDERING_INTENT_TYPES` for valid options.

        .. versionadded:: 0.5.4
        )r   ZMagickGetImageRenderingIntentr  r7   )r  ri_indexr  r  r  rendering_intent	  s    zBaseImage.rendering_intentc             C   s,   t jtd|d t|}t| j| d S )Nz!wand.image.RENDERING_INTENT_TYPES)r  )r   r#  r7   rp   r   ZMagickSetImageRenderingIntentr  )r  r4  r  r  r  r  r  	  s
    
c             C   s<   t d}t d}t| j||}|s0|   |j|jfS )z(:class:`tuple`) Resolution of this image.

        .. versionadded:: 0.3.0

        .. versionchanged:: 0.5.8
           Resolution returns a tuple of float values to
           match ImageMagick's behavior.
        g        )r  r  r   ZMagickGetImageResolutionr  r  r4  )r  r  r  r  r  r  r  
resolution 	  s    


zBaseImage.resolutionc             C   sr   t |tjr|\}}n t |tjr.|| }}ntd| jdkrRt| j	||}nt
| j	||}|sn|   d S )Nz;resolution must be a (x, y) pair or a float of the same x/y)r   r   )r  r   r8  r  Realr  r  r   MagickSetResolutionr  ZMagickSetImageResolutionr  )r  geometryr  r  r  r  r  r  r  1	  s    

c                sH   t d}t| jt | t fddt|jD }t	  |S )a{  (:class:`tuple`) Factors used in sampling data streams.
        This can be set by given it a string ``"4:2:2"``, or tuple of numbers
        ``(2, 1, 1)``. However the given string value will be parsed to aspect
        ratio (i.e. ``"4:2:2"`` internally becomes ``"2,1"``).

        .. note::
            This property is only used by YUV, DPX, & EXR encoders. For
            JPEG & TIFF set ``"jpeg:sampling-factor"`` on
            :attr:`Image.options` dictionary::

                with Image(filename='input.jpg') as img:
                    img.options['jpeg:sampling-factor'] = '2x1'

        .. versionadded:: 0.6.3
        r   c             3   s   | ]} | V  qd S )Nr  ).0r  )factorsr  r  	<genexpr>V	  s    z-BaseImage.sampling_factors.<locals>.<genexpr>)
r  rh  r   ZMagickGetSamplingFactorsr  r  r  r   r4  rP  )r  factors_lenZfactors_tupler  )r  r  sampling_factorsB	  s    

zBaseImage.sampling_factorsc             C   s   t |trPt }tt|t|}||j@ dkrB|j	|j	f}ql|j	|j
f}nt |tjsltdt| t|}tj| | }t| j|| d S )Nr   z9sampling_factors must be a sequence of real numbers, not )r  r   r   r   ParseGeometryr	   r  r  
SigmaValuerhosigmar   r8  r  r  r  r  r   ZMagickSetSamplingFactorsr  )r  r  geometry_infoflagsr  Zfactors_ptrr  r  r  r  Z	  s    

c             C   s   t | jS )z(:class:`numbers.Integral`) The scene number of the current frame
        within an animated image.

        .. versionadded:: 0.5.4
        )r   ZMagickGetImageScener  )r  r  r  r  scenek	  s    zBaseImage.scenec             C   s   t j|d t| j| d S )N)r  )r   r[  r   ZMagickSetImageScener  )r  r4  r  r  r  r  t	  s    c             C   s   | j S )z(:class:`numbers.Integral`) The seed for random number generator.

        .. warning::

            This property is only available with ImageMagick 7.0.8-41, or
            greater.

        .. versionadded:: 0.5.5
        )_seed)r  r  r  r  seedy	  s    zBaseImage.seedc             C   s:   t jd krd}t|tj|d || _t | j| d S )Nz:Property requires ImageMagick version 7.0.8-41 or greater.)r  )r   ZMagickSetSeedr   r   r[  r  r  )r  r4  r  r  r  r  r  	  s    
c             C   s0   d}t | j}|r,tt|}t |}|S )zx(:class:`str`) The SHA-256 message digest for the image pixel
        stream.

        .. versionadded:: 0.1.9

        N)r   ZMagickGetImageSignaturer  r   r  rO  rP  )r  Zsig_strZsig_pr  r  r  r  	  s    
zBaseImage.signaturec             C   s   | j | jfS )a  (:class:`tuple`) The pair of (:attr:`width`, :attr:`height`).

        .. note::

            When working with animations, or other layer-based image formats,
            the :attr:`width` & :attr:`height` properties are referencing the
            last frame read into the image stack. To get the :attr:`size`
            of the entire animated images, call
            :meth:`Image.coalesce() <wand.image.BaseImage.coalesce>` method
            immediately after reading the image.
        )r  r  )r  r  r  r  r  	  s    zBaseImage.sizec             C   s   |   \}}|S )z(:class:`numbers.Real`) The skewness of the image.

        .. tip::

            If you want both :attr:`kurtosis` & :attr:`skewness`, it
            would be faster to call :meth:`kurtosis_channel()` directly.

        .. versionadded:: 0.5.3
        )rd  )r  rf  sr  r  r  skewness	  s    zBaseImage.skewnessc             C   s   |   \}}|S )a	  (:class:`numbers.Real`) The standard deviation of the image.

        .. tip::

            If you want both :attr:`mean` & :attr:`standard_deviation`, it
            would be faster to call :meth:`mean_channel()` directly.

        .. versionadded:: 0.5.3
        )ro  )r  rf  r  r  r  r  r  	  s    zBaseImage.standard_deviationc             C   s   | j d }|rt|S d S )Nstroke)r  r   )r  r  r  r  r  rG  	  s    
zBaseImage.stroke_colorc             C   sP   t |trt|}t |tr*|j| jd< n"|d kr<| jd= ntdt| d S )Nr  z-stroke_color must be a wand.color.Color, not )r  r   r   rN  r  r  r  )r  r  r  r  r  rG  	  s    


c             C   s   | j d }|rt|S d S )Nstrokewidth)r  r  )r  r  r  r  r  rH  	  s    
zBaseImage.stroke_widthc             C   s   t j|d t|| jd< d S )N)rH  r  )r   rQ  r  r  )r  r  r  r  r  rH  	  s    c             C   s   t | jS )zh(:class:`numbers.Integral`) Internal clock for animated images.
        .. versionadded:: 0.5.4
        )r   ZMagickGetImageTicksPerSecondr  )r  r  r  r  ticks_per_second	  s    zBaseImage.ticks_per_secondc             C   s*   t j|d t| j|}|s&|   d S )N)r  )r   r[  r   ZMagickSetImageTicksPerSecondr  r  )r  r4  r  r  r  r  r  	  s    c             C   s$   t | j}|s|   tt| S )z(:class:`basestring`) The image type.

        Defines image type as in :const:`IMAGE_TYPES` enumeration.

        It may raise :exc:`ValueError` when the type is unknown.

        .. versionadded:: 0.2.2

        )r   ZMagickGetImageTyper  r  r/   r   )r  Zimage_type_indexr  r  r  r  	  s    zBaseImage.typec             C   s4   t jtd|d t| jt|}|s0|   d S )Nzwand.image.IMAGE_TYPES)r  )r   r#  r/   r   MagickSetImageTyper  rp   r  )r  
image_typer  r  r  r  r  
  s    c             C   s   t | j}tt| S )z9(:class:`basestring`) The resolution units of this image.)r   ZMagickGetImageUnitsr  r<   r   )r  r  r  r  r  units
  s    zBaseImage.unitsc             C   s4   t jtd|d t| jt|}|s0|   d S )Nzwand.image.UNIT_TYPES)r  )r   r#  r<   r   ZMagickSetImageUnitsr  rp   r  )r  r  r  r  r  r  r  
  s
    c             C   s   t | j}t| S )z(:class:`basestring`) The virtual pixel of image.
        This can also be set with a value from :const:`VIRTUAL_PIXEL_METHOD`
        ... versionadded:: 0.4.1
        )r   Z MagickGetImageVirtualPixelMethodr  r;   )r  Zmethod_indexr  r  r  virtual_pixel
  s    zBaseImage.virtual_pixelc             C   s(   t jtd|d t| jt| d S )Nzwand.image.VIRTUAL_PIXEL_METHOD)r  )r   r#  r;   r   Z MagickSetImageVirtualPixelMethodr  rp   )r  rc  r  r  r  r  $
  s    c             C   s0   y| j S  tk
r*   tt| d Y nX dS )zInternal pointer to the MagickWand instance. It may raise
        :exc:`ClosedImageError` when the instance has destroyed already.

        z is closed alreadyN)r2  r   r@   r  )r  r  r  r  r  .
  s    zBaseImage.wandc             C   s4   y
|| _ W n$ tk
r.   tt|d Y nX d S )Nz is not a MagickWand instance)r2  r  r  )r  r  r  r  r  r  9
  s    
c             C   s   | ` d S )N)r2  )r  r  r  r  r  @
  s    c             C   s   t | jS )z4(:class:`numbers.Integral`) The width of this image.)r   ZMagickGetImageWidthr  )r  r  r  r  r  D
  s    zBaseImage.widthc             C   s"   t j|d t| j|| j d S )N)r  )r   r[  r   r\  r  r  )r  r  r  r  r  r  I
  s    c             C   s~   t d}t d}d}d}tdk rBt| j||}|j|jf}n,t d}t| j|||}|j|j|jf}|sz|   |S )z(:class:`tuple`) The chromatic white point for the image.
        With ImageMagick-6 the primary value is ``(x, y)`` coordinates;
        however, ImageMagick-7 has ``(x, y, z)``.

        .. versionadded:: 0.5.2
        g        Ni   )r  r  r   r   ZMagickGetImageWhitePointr  r4  r  )r  r  r  r  r5  r6  r  r  r  white_pointO
  s    


zBaseImage.white_pointc             C   sf   d }t |tjstdtdk r:|\}}t| j||}n|\}}}t| j|||}|sb|   d S )NzPrimary must be a tuplei   )	r  r   r8  r  r   r   ZMagickSetImageWhitePointr  r  )r  r9  r  r  r  r6  r  r  r  r  f
  s    
c             C   s   t | jd}|r(t|}t |}ndS |s4dS tt| }dd| jt	j
| jdd| j| jt	j
| jdd| jt	j
| jddd	}||}|sdS |  d| _dS )	zFallback for :attr:`auto_orient()` method
        (which wraps :c:func:`MagickAutoOrientImage`),
        fixes orientation by checking EXIF data.

        .. versionadded:: 0.4.1

        s   exif:orientationNg     f@)degreeg     V@g     p@)	rK   r  r  r  r  r  r  r  r  r  )r   MagickGetImagePropertyr  r  rO  rP  r4   rt  flopr  partialrotateflip	transpose
transversegetrr  )r  Zv_ptrZexif_orientationZorientation_typeZ	fn_lookupfnr  r  r  _auto_orientt
  s.    	

zBaseImage._auto_orientc             C   s~   d}t |tjr t |ts |}nBt |trR|tkr<t| }qbtjrbtt|}nt	t
|d |dk rztdt
| |S )a  Attempts to resolve user input into a :c:type:`ChannelType` bit-mask.
        User input can be an integer, a string defined in :const:`CHANNELS`,
        or a string following ImageMagick's `CLI format`__.

        __ https://imagemagick.org/script/command-line-options.php#channel

        .. code::

            # User generated bit-mask.
            mask = self._channel_to_mask(CHANNELS['red'] | CHANNELS['green'])
            # Defined constant.
            mask = self._channel_to_mask('red')
            # CLI format.
            mask = self._channel_to_mask('RGB,Sync')

        :param value: Mixed user input.
        :type value: :class:`numbers.Integral` or :class:`basestring`
        :returns: Bit-mask constant.
        :rtype: :class:`int`

        .. versionadded:: 0.5.5
        z? is an invalid channel type; see wand.image.CHANNELS dictionaryr   z-expected value from wand.image.CHANNELS, not )r  r  r  r  r   r"   r   ZParseChannelOptionr	   r  r  r  )r  r4  r  r  r  r  _channel_to_mask
  s    

zBaseImage._channel_to_maskc             C   s   d\}}t jtd|d |dkr&d}n6|dkrJt| jd t|d  }n|dkr\| j| }|d	krjd}n6|d
krt| jd t|d  }n|dkr| j| }||fS )a  Calculate the top/left offset by a given gravity.

        Some methods in MagickWand's C-API do not respect gravity, but
        instead, expect a x/y offset. This is confusing to folks coming from
        the CLI documentation that does respect gravity

        :param gravity: Value from :const:`GRAVITY_TYPES`.
        :type gravity: :class:`basestring`
        :raises: :class:`ValueError` if gravity is no known.
        :returns: :class:`numbers.Intergal` top, :class:`numbers.Intergal` left

        .. versionadded:: 0.5.3
        )r   r   zwand.image.GRAVITY_TYPES)rY  )r'  r(  r)  r   )r*  r+  r,  r^   )r-  r.  r/  )r'  r*  r-  )r(  r+  r.  )r)  r,  r/  )r   r#  r-   rt  r  r  )r  rY  r  r  topleftr  r  r  _gravity_to_offset
  s     

zBaseImage._gravity_to_offset        c             C   s~   t j||d |dkr(t| j||}nR| |}tdk rNt| j|||}n,t| j|}t| j||}t| j| |S )az  Adaptively blurs the image by decreasing Gaussian as the operator
        approaches detected edges.

        :see: Example of :ref:`adaptive_blur`.

        :param radius: size of gaussian aperture.
        :type radius: :class:`numbers.Real`
        :param sigma: Standard deviation of the gaussian filter.
        :type sigma: :class:`numbers.Real`
        :param channel: Apply the blur effect on a specific channel.
                        See :const:`CHANNELS`.
        :type channel: :class:`basestring`

        .. versionadded:: 0.5.3

        .. versionchanged:: 0.5.5
           Added optional ``channel`` argument
        )radiusr  Ni   )	r   rQ  r   ZMagickAdaptiveBlurImager  r  r   ZMagickAdaptiveBlurImageChannelMagickSetImageChannelMask)r  r  r  channelr  
channel_chr  r  r  r  adaptive_blur
  s    
zBaseImage.adaptive_blurc             C   s:   |dkr| j }|dkr| j}tj||d t| j||S )a  Adaptively resize image by applying Mesh interpolation.

        :param columns: width of resized image.
        :type columns: :class:`numbers.Integral`
        :param rows: hight of resized image.
        :type rows: :class:`numbers.Integral`

        .. versionadded:: 0.5.3
        N)columnsrows)r  r  r   rA  r   ZMagickAdaptiveResizeImager  )r  r  r  r  r  r  adaptive_resize  s    zBaseImage.adaptive_resizec             C   s~   t j||d |dkr(t| j||}nR| |}tdk rNt| j|||}n,t| j|}t| j||}t| j| |S )a  Adaptively sharpens the image by sharpening more intensely near
        image edges and less intensely far from edges.

        :see: Example of :ref:`adaptive_sharpen`.

        :param radius: size of gaussian aperture.
        :type radius: :class:`numbers.Real`
        :param sigma: Standard deviation of the gaussian filter.
        :type sigma: :class:`numbers.Real`
        :param channel: Apply the sharpen effect on a specific channel.
                        See :const:`CHANNELS`.
        :type channel: :class:`basestring`

        .. versionadded:: 0.5.3

        .. versionchanged:: 0.5.5
           Added optional ``channel`` argument
        )r  r  Ni   )	r   rQ  r   ZMagickAdaptiveSharpenImager  r  r   Z!MagickAdaptiveSharpenImageChannelr  )r  r  r  r  r  r  r  r  r  r  adaptive_sharpen  s     
zBaseImage.adaptive_sharpenc             C   s<   t j||d t j|d tdk r*t|}t| j|||S )a5  Applies threshold for each pixel based on neighboring pixel values.

        :param width: size of neighboring pixels on the X-axis.
        :type width: :class:`numbers.Integral`
        :param height: size of neighboring pixels on the Y-axis.
        :type height: :class:`numbers.Integral`
        :param offset: normalized number between `0.0` and
                       :attr:`quantum_range`. Forces the pixels to black if
                       values are below ``offset``.
        :type offset: :class:`numbers.Real`

        .. versionadded:: 0.5.3
        )r  r  )offseti   )r   rA  rQ  r   rt  r   ZMagickAdaptiveThresholdImager  )r  r  r  r  r  r  r  adaptive_thresholdG  s    
zBaseImage.adaptive_thresholdr   c             C   sV   ddl m} t||s&tdt| tj|||d t|}t	| j
|j||||S )a  Draws text on an image. This method differs from :meth:`caption()`
        as it uses :class:`~wand.drawing.Drawing` class to manage the
        font configuration & style context.

        .. code::

            from wand.drawing import Drawing
            from wand.image import Image

            with Image(filename='input.jpg') as img:
                with Drawing() as ctx:
                    ctx.font_family = 'Times New Roman, Nimbus Roman No9'
                    ctx.font_size = 18
                    ctx.text_decoration = 'underline'
                    ctx.text_kerning = -1
                    img.annotate('Hello World', ctx, left=20, baseline=50)
                img.save(filename='output.jpg')

        :param text: String to annotate on image.
        :type text: :class:`basestring`
        :param drawing_wand: Font configuration & style context.
        :type text: :class:`wand.drawing.Drawing`
        :param left: X-axis offset of the text baseline.
        :type left: :class:`numbers.Real`
        :param baseline: Y-axis offset of the bottom of the text.
        :type baseline: :class:`numbers.Real`
        :param angle: Degree rotation to draw text at.
        :type angle: :class:`numbers.Real`

        .. versionadded:: 0.5.6
        r   )Drawingz?drawing_wand must be in instances of wand.drawing.Drawing, not )r  baselineangle)Zdrawingr  r  r  r  r   rQ  r	   r   ZMagickAnnotateImager  r2  )r  r   Zdrawing_wandr  r  r  r  Zbtextr  r  r  annotate]  s    "
zBaseImage.annotatec             C   s   t | jS )zMAdjust the gamma level of an image.

        .. versionadded:: 0.5.4
        )r   ZMagickAutoGammaImager  )r  r  r  r  
auto_gamma  s    zBaseImage.auto_gammac             C   s   t | jS )zgScale the minimum and maximum values to a full quantum range.

        .. versionadded:: 0.5.4
        )r   ZMagickAutoLevelImager  )r  r  r  r  
auto_level  s    zBaseImage.auto_levelc             C   s.   yt | jS  tk
r(   |   dS X dS )a\  Adjusts an image so that its orientation is suitable
        for viewing (i.e. top-left orientation). If available it uses
        :c:func:`MagickAutoOrientImage` (was added in ImageMagick 6.8.9+)
        if you have an older magick library,
        it will use :attr:`_auto_orient()` method for fallback.

        .. versionadded:: 0.4.1

        TN)r   ZMagickAutoOrientImager  AttributeErrorr  )r  r  r  r  auto_orient  s
    zBaseImage.auto_orientr\   c             C   s>   t jdkrd}t|tjtd|d t|}t | j|S )a  Automatically performs threshold method to reduce grayscale data
        down to a binary black & white image. Included algorithms are
        Kapur, Otsu, and Triangle methods.

        .. warning::

            This class method is only available with ImageMagick 7.0.8-41, or
            greater.

        :param method: Which threshold method to apply.
                       See :const:`AUTO_THRESHOLD_METHODS`.
                       Defaults to ``'kapur'``.
        :type method: :class:`basestring`
        :raises WandLibraryVersionError: if function is not available on
                                         system's library.

        .. versionadded:: 0.5.5
        Nz8Method requires ImageMagick version 7.0.8-41 or greater.z!wand.image.AUTO_THRESHOLD_METHODS)rc  )r   ZMagickAutoThresholdImager   r   r#  r!   rp   r  )r  rc  r  ra  r  r  r  auto_threshold  s    

zBaseImage.auto_thresholdc          	   C   sB   t |trt|}tj|d | t| j|j}W dQ R X |S )zForces all pixels above a given color as black. Leaves pixels
        above threshold unaltered.

        :param threshold: Color to be referenced as a threshold.
        :type threshold: :class:`Color`

        .. versionadded:: 0.5.3
        )r   N)	r  r   r   r   r  r   ZMagickBlackThresholdImager  r2  )r  r   r  r  r  r  black_threshold  s    
zBaseImage.black_threshold      ?c             C   s   t j|d t| j|S )zMutes colors of the image by shifting blue values.

        :see: Example of :ref:`blue_shift`

        :param factor: Amount to adjust values.
        :type factor: :class:`numbers.Real`

        .. versionadded:: 0.5.3
        )factor)r   rQ  r   ZMagickBlueShiftImager  )r  r  r  r  r  
blue_shift  s    zBaseImage.blue_shiftc             C   s~   t j||d |dkr(t| j||}nR| |}tdk rNt| j|||}n,t| j|}t| j||}t| j| |S )aF  Blurs the image.  Convolve the image with a gaussian operator
        of the given ``radius`` and standard deviation (``sigma``).
        For reasonable results, the ``radius`` should be larger
        than ``sigma``.  Use a ``radius`` of 0 and :meth:`blur()` selects
        a suitable ``radius`` for you.

        :see: Example of :ref:`blur`.

        :param radius: the radius of the, in pixels,
                       not counting the center pixel. Default is ``0.0``.
        :type radius: :class:`numbers.Real`
        :param sigma: the standard deviation of the, in pixels. Default value
                      is ``0.0``.
        :type sigma: :class:`numbers.Real`
        :param channel: Optional color channel to apply blur. See
                        :const:`CHANNELS`.
        :type channel: :class:`basestring`

        .. versionadded:: 0.4.5

        .. versionchanged:: 0.5.5
           Added optional ``channel`` argument.

        .. versionchanged:: 0.5.7
           Positional arguments ``radius`` & ``sigman`` have been converted to
           key-word arguments.
        )r  r  Ni   )	r   rQ  r   ZMagickBlurImager  r  r   ZMagickBlurImageChannelr  )r  r  r  r  r  r  r  r  r  r  r     s    
zBaseImage.blurrN   c          	   C   s   t |trt|}tj|d |T tdk rBt| j|j	||}n0tj
td|d t|}t| j|j	|||}W dQ R X |S )ay  Surrounds the image with a border.

        :param bordercolor: the border color pixel wand
        :type image: :class:`~wand.color.Color`
        :param width: the border width
        :type width: :class:`numbers.Integral`
        :param height: the border height
        :type height: :class:`numbers.Integral`
        :param compose: Use composite operator when applying frame. Only used
                        if called with ImageMagick 7+.
        :type compose: :class:`basestring`

        .. versionadded:: 0.3.0
        .. versionchanged:: 0.5.0
           Added ``compose`` paramater, and ImageMagick 7 support.
        )r  i   zwand.image.COMPOSITE_OPERATORS)r=  N)r  r   r   r   r  r   r   ZMagickBorderImager  r2  r#  r%   rp   )r  r  r  r  r=  r  Zcompose_idxr  r  r  border  s    


zBaseImage.borderc             C   s~   t j||d |dkr(t| j||}nR| |}tdk rNt| j|||}n,t| j|}t| j||}t| j| |S )a  Converts ``brightness`` & ``contrast`` paramaters into a slope &
        intercept, and applies a polynomial function.

        :param brightness: between ``-100.0`` and ``100.0``. Default is ``0.0``
                           for unchanged.
        :type brightness: :class:`numbers.Real`
        :param contrast: between ``-100.0`` and ``100.0``. Default is ``0.0``
                         for unchanged.
        :type contrast: :class:`numbers.Real`
        :param channel: Isolate a single color channel to apply contrast.
                        See :const:`CHANNELS`.

        .. versionadded:: 0.5.4

        .. versionchanged:: 0.5.5
           Optional ``channel`` argument added.
        )
brightnesscontrastNi   )	r   rQ  r   ZMagickBrightnessContrastImager  r  r   Z$MagickBrightnessContrastImageChannelr  )r  r  r  r  r  r  r  r  r  r  brightness_contrast<  s"    
zBaseImage.brightness_contrast      ?皙?333333?c             C   s<   t jdkrd}t|tj||||d t | j||||S )a"  Detect edges by leveraging a multi-stage Canny algorithm.

        .. warning::

            This class method is only available with ImageMagick 7.0.8-41, or
            greater.

        :param radius: Size of gaussian filter.
        :type radius: :class:`numbers.Real`
        :param sigma: Standard deviation of gaussian filter.
        :type sigma: :class:`numbers.Real`
        :param lower_percent: Normalized lower threshold. Values between
                              ``0.0`` (0%) and ``1.0`` (100%). The default
                              value is ``0.1`` or 10%.
        :type lower_percent: :class:`numbers.Real`
        :param upper_percent: Normalized upper threshold. Values between
                              ``0.0`` (0%) and ``1.0`` (100%). The default
                              value is ``0.3`` or 30%.
        :type upper_percent: :class:`numbers.Real`
        :raises WandLibraryVersionError: if function is not available on
                                         system's library.

        .. versionadded:: 0.5.5
        Nz8Method requires ImageMagick version 7.0.8-41 or greater.)r  r  lower_percentupper_percent)r   ZMagickCannyEdgeImager   r   rQ  r  )r  r  r  r  r  r  r  r  r  cannyd  s    
zBaseImage.cannyc       
   
   C   sF  t j||d |dk	r0t|ts0tdt| |dk	rHt jtd|d |dkr\| j| }nt j|d |dkr|| j	| }nt j|d |dkry| j
}|dkrt W n tk
r   tdY nX t p}t|j|| ||_
|p| j|_td	}	t|j|	j W dQ R X |jd
|d d | ||| W dQ R X dS )a  Writes a caption ``text`` into the position.

        :param text: text to write
        :type text: :class:`basestring`
        :param left: x offset in pixels
        :type left: :class:`numbers.Integral`
        :param top: y offset in pixels
        :type top: :class:`numbers.Integral`
        :param width: width of caption in pixels.
                      default is :attr:`width` of the image
        :type width: :class:`numbers.Integral`
        :param height: height of caption in pixels.
                       default is :attr:`height` of the image
        :type height: :class:`numbers.Integral`
        :param font: font to use.  default is :attr:`font` of the image
        :type font: :class:`wand.font.Font`
        :param gravity: text placement gravity.
                        uses the current :attr:`gravity` setting of the image
                        by default
        :type gravity: :class:`basestring`

        .. versionadded:: 0.3.0

        )r  r  Nz#font must be a wand.font.Font, not zwand.image.GRAVITY_TYPES)rY  )r  )r  z+font must be specified or existing in imagerU   s   caption:zutf-8)filename)r   rA  r  r   r  r  r#  r-   r  r  rL  rB   r   r\  r  rY  r   r3  r2  readrx  r6  )
r  r   r  r  r  r  rL  rY  Z	textboardr1  r  r  r  r}    s:    

zBaseImage.captionc             C   s
   |  |S )zPAlias for :meth:`color_decision_list`.

        .. versionadded:: 0.5.7
        )color_decision_list)r  cccr  r  r  cdl  s    zBaseImage.cdlc             C   s   t j||d t| j||S )aZ  Transform an image into a simulated charcoal drawing.

        :see: Example of :ref:`charcoal`.

        :param radius: The size of the Gaussian operator.
        :type radius: :class:`numbers.Real`
        :param sigma: The standard deviation of the Gaussian.
        :type sigma: :class:`numbers.Real`

        .. versionadded:: 0.5.3
        )r  r  )r   rQ  r   ZMagickCharcoalImager  )r  r  r  r  r  r  charcoal  s    zBaseImage.charcoalc             C   s0   t j||d t j||d t| j||||S )a  Removes a region of an image, and reduces the image size
        accordingly.

        :param width: Size of region.
        :type width: :class:`numbers.Integral`
        :param height: Size of region.
        :type height: :class:`numbers.Integral`
        :param x: Offset on the X-axis.
        :type x: :class:`numbers.Integral`
        :param y: Offset on the Y-axis.
        :type y: :class:`numbers.Integral`

        .. versionadded:: 0.5.5
        )r  r  )r  r  )r   r[  rA  r   ZMagickChopImager  )r  r  r  r  r  r  r  r  chop  s    zBaseImage.chopc             C   sF   t jdkrd}t|tj||d tj||d t | j||||S )a  Contrast limited adaptive histogram equalization.

        .. warning::

            The CLAHE method is only available with ImageMagick-7.

        :param width: Tile division width.
        :type width: :class:`numbers.Integral`
        :param height: Tile division height.
        :type height: :class:`numbers.Integral`
        :param number_bins: Histogram bins.
        :type number_bins: :class:`numbers.Real`
        :param clip_limit: contrast limit.
        :type clip_limit: :class:`numbers.Real`
        :raises WandLibraryVersionError: If system's version of ImageMagick
                                         does not support this method.

        .. versionadded:: 0.5.5
        Nz0CLAHE method not defined in ImageMagick library.)r  r  )number_bins
clip_limit)r   ZMagickCLAHEImager   r   r[  rQ  r  )r  r  r  r  r  r  r  r  r  clahe  s    
zBaseImage.clahec             C   sd   |dkrt | j}nJ| |}tdk r8t | j|}n(t | j|}t | j}t | j| |S )a{  Restrict color values between 0 and quantum range. This is useful
        when applying arithmetic operations that could result in color values
        over/under-flowing.

        :param channel: Optional color channel.
        :type channel: :class:`basestring`

        .. versionadded:: 0.5.0

        .. versionchanged:: 0.5.5
           Added ``channel`` argument.
        Ni   )r   ZMagickClampImager  r  r   ZMagickClampImageChannelr  )r  r  r  r  r  r  r  r  clamp  s    
zBaseImage.clampc             C   s
   t | dS )a<  Clones the image. It is equivalent to call :class:`Image` with
        ``image`` parameter. ::

            with img.clone() as cloned:
                # manipulate the cloned image
                pass

        :returns: the cloned new image
        :rtype: :class:`Image`

        .. versionadded:: 0.1.1

        )r	  )rB   )r  r  r  r  r  (  s    zBaseImage.clonerK   c             C   s   t |tstdt| tdk rZ|dkr<t| j|j}q| |}t	| j||j}nnt
jtd|d t|}|dkrt| j|j|}n8| |}t| j|}t| j|j|}t| j| |S )a  Replace color values by referencing another image as a Color
        Look Up Table.

        :param image: Color Look Up Table image.
        :type image: :class:`wand.image.BaseImage`
        :param method: Pixel Interpolate method. Only available with
                       ImageMagick-7. See :const:`PIXEL_INTERPOLATE_METHODS`
        :type method: :class:`basestring`
        :param channel: Optional color channel to target. See
                        :const:`CHANNELS`
        :type channel: :class:`basestring`

        .. versionadded:: 0.5.0

        .. versionchanged:: 0.5.5
           Added optional ``channel`` argument.
        z image must be a base image, not i   Nz$wand.image.PIXEL_INTERPOLATE_METHODS)Zpixel_interpolate_method)r  r=   r  r  r   r   ZMagickClutImager  r  ZMagickClutImageChannelr   r#  r6   rp   r  )r  r	  rc  r  r  r  ra  r  r  r  r  clut8  s(    




zBaseImage.clutc             C   s&   t | j}|r|| _|   t|S )a  Rebuilds image sequence with each frame size the same as first frame,
        and composites each frame atop of previous.

        .. note::

            Only affects GIF, and other formats with multiple pages/layers.

        .. versionadded:: 0.5.0
        )r   MagickCoalesceImagesr  reset_sequencer  )r  r  r  r  r  r0  d  s
    zBaseImage.coalescec             C   s   t | jt|S )a  Applies color correction from a Color Correction Collection (CCC)
        xml string. An example of xml:

        .. code-block:: xml

            <ColorCorrectionCollection xmlns="urn:ASC:CDL:v1.2">
                <ColorCorrection id="cc03345">
                    <SOPNode>
                        <Slope> 0.9 1.2 0.5 </Slope>
                        <Offset> 0.4 -0.5 0.6 </Offset>
                        <Power> 1.0 0.8 1.5 </Power>
                    </SOPNode>
                    <SATNode>
                        <Saturation> 0.85 </Saturation>
                    </SATNode>
                </ColorCorrection>
            </ColorCorrectionCollection>

        :param ccc: A XML string of the CCC contents.
        :type ccc: :class:`basestring`

        .. versionadded:: 0.5.7
        )r   ZMagickColorDecisionListImager  r	   )r  r  r  r  r  r  v  s    zBaseImage.color_decision_listc          	   C   s   t |tjstdt| |dk s.|| jkr6td|rt |trLt|}t |tsftdt| |$ t	
| j||j}|s|   W dQ R X nBt	 }t	| j||}|st	|}|   t|}t	|}|S )a  Get & Set a color at a palette index. If ``color`` is given,
        the color at the index location will be set & returned. Omitting the
        ``color`` argument will only return the color value at index.

        Valid indexes are between ``0`` and total :attr:`colors` of the image.

        .. note::

            Ensure the image type is set to ``'palette'`` before calling the
            :meth:`color_map` method. For example::

                with Image(filename='graph.png') as img:
                    img.type = 'palette'
                    palette = [img.color_map(idx) for idx in range(img.colors)]
                    # ...

        :param index: The color postion of the image palette.
        :type index: :class:`numbers.Integral`
        :param color: Optional color to _set_ at the given index.
        :type color: :class:`wand.color.Color`
        :returns: Color at index.
        :rtype: :class:`wand.color.Color`

        .. versionadded:: 0.5.3
        zindex most be an integer, not r   zindex is out of palette rangez$expecting in instance of Color, not N)r  r  r  r  r  r;  r  r   r   r   ZMagickSetImageColormapColorr  r2  r  r-  ZMagickGetImageColormapColorr0  r/  )r  rp   r  r  Z	color_ptrr  r  r  	color_map  s4    




zBaseImage.color_mapc             C   s   t |tjstdt| t|}d}g }xj|D ]b}t |tjsRtdt| |dkrdt|}n|t|krxtdx|D ]}|t| q~W q2W t	d
||d|}t }tdk rt|}	nt||}	t|}t| j|	}
t|	}	|
S )a.  Adjust color values by applying a matrix transform per pixel.

        Matrix should be given as 2D list, with a max size of 6x6.

        An example of 3x3 matrix::

            matrix = [
                [1.0, 0.0, 0.0],
                [0.0, 1.0, 0.0],
                [0.0, 0.0, 1.0],
            ]

        Which would translate RGB color channels by calculating the
        following:

        .. math::

            \begin{aligned}
            red' &= 1.0 * red + 0.0 * green + 0.0 * blue\\
            green' &= 0.0 * red + 1.0 * green + 0.0 * blue\\
            blue' &= 0.0 * red + 0.0 * green + 1.0 * blue\\
            \end{aligned}

        For RGB colorspace images, the rows & columns are laid out as:

        +---------+-----+-------+------+------+-------+--------+
        |         | Red | Green | Blue | n/a  | Alpha | Offset |
        +=========+=====+=======+======+======+=======+========+
        | Red'    | 1   | 0     | 0    | 0    | 0     | 0      |
        +---------+-----+-------+------+------+-------+--------+
        | Green'  | 0   | 1     | 0    | 0    | 0     | 0      |
        +---------+-----+-------+------+------+-------+--------+
        | Blue'   | 0   | 0     | 1    | 0    | 0     | 0      |
        +---------+-----+-------+------+------+-------+--------+
        | n/a     | 0   | 0     | 0    | 0    | 0     | 0      |
        +---------+-----+-------+------+------+-------+--------+
        | Alpha'  | 0   | 0     | 0    | 0    | 0     | 0      |
        +---------+-----+-------+------+------+-------+--------+
        | Offset' | 0   | 0     | 0    | 0    | 0     | 0      |
        +---------+-----+-------+------+------+-------+--------+

        Or for a CMYK colorspace image:

        +----------+------+--------+---------+-------+-------+--------+
        |          | Cyan | Yellow | Magenta | Black | Alpha | Offset |
        +==========+======+========+=========+=======+=======+========+
        | Cyan'    | 1    | 0      | 0       | 0     | 0     | 0      |
        +----------+------+--------+---------+-------+-------+--------+
        | Yellow'  | 0    | 1      | 0       | 0     | 0     | 0      |
        +----------+------+--------+---------+-------+-------+--------+
        | Magenta' | 0    | 0      | 1       | 0     | 0     | 0      |
        +----------+------+--------+---------+-------+-------+--------+
        | Black'   | 0    | 0      | 0       | 1     | 0     | 0      |
        +----------+------+--------+---------+-------+-------+--------+
        | Alpha'   | 0    | 0      | 0       | 0     | 0     | 0      |
        +----------+------+--------+---------+-------+-------+--------+
        | Offset'  | 0    | 0      | 0       | 0     | 0     | 0      |
        +----------+------+--------+---------+-------+-------+--------+

        See `color-matrix`__ for examples.

        __ https://www.imagemagick.org/Usage/color_mods/#color-matrix

        :see: Example of :ref:`color_matrix`.

        :param matrix: 2D List of doubles.
        :type matrix: :class:`collections.abc.Sequence`

        .. versionadded:: 0.5.3
        zmatrix must be a sequence, not Nz#nested row must be a sequence, not z!rows have different column lengthz{0}x{1}:{2},i   )r  r   r8  r  r  r  r  appendr  r	   r  joinr   AcquireExceptionInfor   AcquireKernelInfoDestroyExceptionInfor   ZMagickColorMatrixImager  DestroyKernelInfo)r  Zmatrixr  r  valuesrowcolumnkernelexception_infokernel_infor  r  r  r  color_matrix  s4    I




zBaseImage.color_matrixc          
   C   s   t |trt|}t |tr$t|}tj||d tjdkrHd}t||* | t| j|j	|j	}W dQ R X W dQ R X |S )a  Forces all pixels in color range to white, and all other pixels to
        black.

        .. note::

            This method is only works with ImageMagick-7.0.10, or later.

        :param start: Color to begin color range.
        :type start: :class:`wand.color.Color`
        :param stop: Color to end color range.
        :type stop: :class:`wand.color.Color`

        .. versionadded:: 0.6.4
        )r  r  Nz'Method "color_threshold" not available.)
r  r   r   r   r  r   ZMagickColorThresholdImager   r  r2  )r  r  r  r  r  r  r  r  color_threshold-  s    


zBaseImage.color_thresholdc          
   C   sj   t |trt|}t |tr$t|}tj||d |* | t| j|j|j}W dQ R X W dQ R X |S )a  Blends a given fill color over the image. The amount of blend is
        determined by the color channels given by the ``alpha`` argument.

        :see: Example of :ref:`colorize`.

        :param color: Color to paint image with.
        :type color: :class:`wand.color.Color`
        :param alpha: Defines how to blend color.
        :type alpha: :class:`wand.color.Color`

        .. versionadded:: 0.5.3
        )r  rm   N)	r  r   r   r   r  r   ZMagickColorizeImager  r2  )r  r  rm   r  r  r  r  r   M  s    

zBaseImage.colorizeru   rt   c             C   sp   t jtd|d t| j t|}| |}tdk rHt	| j|}nt	| j|}|rh|| _| 
  t|S )a  Creates an image where each color channel is assigned by a grayscale
        image in a sequence.

        .. warning::

            If your using ImageMagick-6, use ``channel`` argument to control
            the color-channel order.  With ImageMagick-7, the ``channel``
            argument has been replaced with ``colorspace``.

        For example::

            for wand.image import Image

            with Image() as img:
                img.read(filename='red_channel.png')
                img.read(filename='green_channel.png')
                img.read(filename='blue_channel.png')
                img.combine(colorspace='rgb')
                img.save(filename='output.png')

        :param channel: Determines the colorchannel ordering of the
                        sequence. Only used for ImageMagick-6.
                        See :const:`CHANNELS`.
        :type channel: :class:`basestring`
        :param colorspace: Determines the colorchannel ordering of the
                           sequence. Only used for ImageMagick-7.
                           See :const:`COLORSPACE_TYPES`.
        :type colorspace: :class:`basestring`

        .. versionadded:: 0.5.9
        zwand.image.COLORSPACE_TYPES)r  i   )r   r#  r#   r   r&  r  rp   r  r   ZMagickCombineImagesr  r  )r  r  r  Zcolorspace_cZ	channel_cnew_wandr  r  r  combineh  s    "

zBaseImage.combinec             C   s   t jtd|d |r8t|tr$|j}t| jdt	| |r`t|trL|j}t| jdt	| t
|}td}t| j|j|t|}tt||jfS )ac  Compares an image with another, and returns a reconstructed
        image & computed distortion. The reconstructed image will show the
        differences colored with ``highlight``, and similarities with
        ``lowlight``.

        If you need the computed distortion between to images without a
        image being reconstructed, use :meth:`get_image_distortion()` method.

        Set :attr:`fuzz` property to adjust pixel-compare thresholds.

        For example::

            from wand.image import Image

            with Image(filename='input.jpg') as base:
                with Image(filename='subject.jpg') as img:
                    base.fuzz = base.quantum_range * 0.20  # Threshold of 20%
                    result_image, result_metric = base.compare(img)
                    with result_image:
                        result_image.save(filename='diff.jpg')

        :param image: The reference image
        :type image: :class:`wand.image.Image`
        :param metric: The metric type to use for comparing. See
                       :const:`COMPARE_METRICS`
        :type metric: :class:`basestring`
        :param highlight: Set the color of the delta pixels in the resulting
                          difference image.
        :type highlight: :class:`~wand.color.Color` or :class:`basestring`
        :param lowlight: Set the color of the similar pixels in the resulting
                          difference image.
        :type lowlight: :class:`~wand.color.Color` or :class:`basestring`
        :returns: The difference image(:class:`wand.image.Image`),
                  the computed distortion between the images
                  (:class:`numbers.Real`)
        :rtype: :class:`tuple` ( :class:`Image`, :class:`numbers.Real` )

        .. versionadded:: 0.4.3

        .. versionchanged:: 0.5.3
           Added support for ``highlight`` & ``lowlight``.
        zwand.image.COMPARE_METRICS)metrics   compare:highlight-colors   compare:lowlight-colorg        )r   r#  r$   r  r   rN  r   MagickSetImageArtifactr  r	   rp   r  r  ZMagickCompareImagesr  rB   r=   r4  )r  r	  r  	highlightZlowlightZ
distortionZcompared_imager  r  r  compare  s*    -





zBaseImage.comparec             C   s~   t jdkrd}t|tjtd|d |dk	rJd}t|}t | j|| t	|}t | j|}t
|sr|   tt|S )a  Performs `complex`_ mathematics against two images in a sequence,
        and generates a new image with two results.

        .. seealso::

            :meth:`forward_fourier_transform` &
            :meth:`inverse_fourier_transform`

        .. code::

            from wand.image import Image

            with Image(filename='real_part.png') as imgA:
                with Image(filename='imaginary_part.png') as imgB:
                    imgA.sequence.append(imgB)
                with imgA.complex('conjugate') as results:
                    results.save(filename='output-%02d.png')

        .. _complex: https://en.wikipedia.org/wiki/Complex_number

        .. warning::

            This class method is only available with ImageMagick 7.0.8-41, or
            greater.

        :param operator: Define which mathematic operator to perform. See
                         :const:`COMPLEX_OPERATORS`.
        :type operator: :class:`basestring`
        :param snr: Optional ``SNR`` parameter for ``'divide'`` operator.
        :type snr: :class:`basestring`
        :raises WandLibraryVersionError: If ImageMagick library does not
                                         support this function.

        .. versionadded:: 0.5.5
        Nz8Method requires ImageMagick version 7.0.8-41 or greater.zwand.image.COMPLEX_OPERATORS)r>  s   complex:snr=float)r   ZMagickComplexImagesr   r   r#  COMPLEX_OPERATORSr   r  r  rp   r  r  rB   r=   )r  r>  Zsnrr  keyvalZoperator_idxr  r  r  r  complex  s    %

zBaseImage.complexr   c       	   	   C   sJ  |dkr6|dkr6|dkr| j }| ||j|j\}}n,|dk	rHtdn|dkrVd}n|dkrbd}tj||d yt|}W n$ t	k
r   t
t|d Y nX |rtj|d t|jtdt|}|s|   t| jtdt|}|s|   tdk r&t| j|j|t|t|}n t| j|j|d	t|t|}|S )
a@  Places the supplied ``image`` over the current image, with the top
        left corner of ``image`` at coordinates ``left``, ``top`` of the
        current image.  The dimensions of the current image are not changed.

        :param image: the image placed over the current image
        :type image: :class:`wand.image.Image`
        :param left: the x-coordinate where `image` will be placed
        :type left: :class:`numbers.Integral`
        :param top: the y-coordinate where `image` will be placed
        :type top: :class:`numbers.Integral`
        :param operator: the operator that affects how the composite
                         is applied to the image.  available values
                         can be found in the :const:`COMPOSITE_OPERATORS`
                         list. Default is ``'over'``.
        :type operator: :class:`basestring`
        :param arguments: Additional numbers given as a geometry string, or
                         comma delimited values. This is needed for
                         ``'blend'``, ``'displace'``, ``'dissolve'``, and
                         ``'modulate'`` operators.
        :type arguments: :class:`basestring`
        :param gravity: Calculate the ``top`` & ``left`` values based on
                        gravity value from :const:`GRAVITY_TYPES`.
        :type: gravity: :class:`basestring`

        .. versionadded:: 0.2.0

        .. versionchanged:: 0.5.3
           The operator can be set, as well as additional composite arguments.

        .. versionchanged:: 0.5.3
           Optional ``gravity`` argument was added.
        Nz+Can not use gravity if top & left are givenr   )r  r  zU is an invalid composite operator type; see wand.image.COMPOSITE_OPERATORS dictionary)	argumentszcompose:argsi   T)rY  r  r  r  r  r   rA  r%   rp   r  r  r  rR  r   r  r  r	   r  r   MagickCompositeImagert  )	r  r	  r  r  r>  r  rY  opr  r  r  r  r6    sF    #



zBaseImage.compositec          	   C   sN  t j|d | |}|rJ|dkrB|dkrB| ||j|j\}}ntd|dkrVd}|dkrbd}t j||d yt	|}	W n$ t
k
r   t
t|d Y nX |rt j|d t|jtdt| t| jtdt| tjrt| j||j|	t|t|}
n<t| j|}t| j|j|	d	t|t|}
t| j| |
S )
a  Composite two images using the particular ``channel``.

        :param channel: the channel type.  available values can be found
                        in the :const:`CHANNELS` mapping
        :param image: the composited source image.
                      (the receiver image becomes the destination)
        :type image: :class:`Image`
        :param operator: the operator that affects how the composite
                         is applied to the image.  available values
                         can be found in the :const:`COMPOSITE_OPERATORS`
                         list
        :type operator: :class:`basestring`
        :param left: the column offset of the composited source image
        :type left: :class:`numbers.Integral`
        :param top: the row offset of the composited source image
        :type top: :class:`numbers.Integral`
        :param arguments: Additional numbers given as a geometry string, or
                         comma delimited values. This is needed for
                         ``'blend'``, ``'displace'``, ``'dissolve'``, and
                         ``'modulate'`` operators.
        :type arguments: :class:`basestring`
        :param gravity: Calculate the ``top`` & ``left`` values based on
                        gravity value from :const:`GRAVITY_TYPES`.
        :type: gravity: :class:`basestring`
        :raises ValueError: when the given ``channel`` or
                            ``operator`` is invalid

        .. versionadded:: 0.3.0

        .. versionchanged:: 0.5.3
           Support for optional composite arguments has been added.

        .. versionchanged:: 0.5.3
           Optional ``gravity`` argument was added.
        )r>  Nz+Can not use gravity if top & left are givenr   )r  r  zU is an invalid composite operator type; see wand.image.COMPOSITE_OPERATORS dictionary)r  zcompose:argsT)r   rR  r  r  r  r  r  rA  r%   rp   r  r  r   r  r  r	   ZMagickCompositeImageChannelrt  r  r  )r  r  r	  r>  r  r  r  rY  ch_constr   r  Zch_maskr  r  r  composite_channel[  sD    '



zBaseImage.composite_channelFc             C   s4   t j|d t| j|}|r,|| _|   t|S )a  Concatenates images in stack into a single image. Left-to-right
        by default, top-to-bottom if ``stacked`` is True.

        :param stacked: stack images in a column, or in a row (default)
        :type stacked: :class:`bool`

        .. versionadded:: 0.5.0
        )stacked)r   r,  r   ZMagickAppendImagesr  r  r  )r  r  r  r  r  r  concat  s    zBaseImage.concatc             K   s  | dd}| dd}| dd}| dd}| dd}| dd}| d	d}| d
d}	| dd}
| dd}| dd}| dd}| dd}| dd}| dd}| dd}tjdkrd}t||dkrtd|dk	rd}t|}t| j|| |dk	r2d}t|}t| j|| |dk	rXd}t|}t| j|| |dk	r~d}t|}t| j|| |dk	rd}t|}t| j|| |dk	rd}t|}t| j|| |	dk	rd}t|	}t| j|| |
dk	rd}t|
}t| j|| |dk	r<d}t|}t| j|| |dk	rbd }t|}t| j|| |rd!}d"}t| j|d" |dk	rd#}t|}t| j|| |dk	rd$}t|}t| j|| |dk	rd%}t|}t| j|| |dk	rd&}t|}t| j|| t	d'}t
}td(kr4t}t|}t| j|t|}g }|r|jrxLt| jD ]>}| }|j||  }tt||| |t| ~qrW t|}n|   |S ))a  Evaluates binary image, and groups connected pixels into objects.
        This method will also return a list of
        :class:`ConnectedComponentObject` instances that will describe an
        object's features.

        .. code::

            from wand.image import Image

            with Image(filename='objects.gif') as img:
                objects = img.connected_components()
            for cc_obj in objects:
                print("{0._id}: {0.size} {0.offset}".format(cc_obj))

            #=> 0: (256, 171) (0, 0)
            #=> 2: (120, 135) (104, 18)
            #=> 3: (50, 36) (129, 44)
            #=> 4: (21, 23) (0, 45)
            #=> 1: (4, 10) (252, 0)

        .. warning::

            This class method is only available with ImageMagick 7.0.8-41, or
            greater.

        .. tip::

            Set :attr:`fuzz` property to increase pixel matching by reducing
            tolerance of color-value comparisons::

                from wand.image import Image
                from wand.version import QUANTUM_RANGE

                with Image(filename='objects.gif') as img:
                    img.fuzz = 0.1 * QUANTUM_RANGE  # 10%
                    objects = img.connected_components()

        :param angle_threshold: Optional argument that merges any region with
                                an equivalent ellipse smaller than a given
                                value. Requires ImageMagick-7.0.9-24, or
                                greater.
        :type angle_threshold: :class:`basestring`
        :param area_threshold: Optional argument to merge objects under an
                               area size.
        :type area_threshold: :class:`basestring`
        :param background_id: Optional argument to identify which object
                              should be the background. Requires
                              ImageMagick-7.0.9-24, or greater.
        :type background_id: :class:`basestring`
        :param circularity_threshold: Optional argument that merges any region
                                      smaller than value defined as:
                                      ``4*pi*area/perimeter^2``. Requires
                                      ImageMagick-7.0.9-24, or greater.
        :type circularity_threshold: :class:`basestring`
        :param connectivity: Either ``4``, or ``8``. A value of ``4`` will
                            evaluate each pixels top-bottom, & left-right
                            neighbors. A value of ``8`` will use the same
                            pixels as with ``4``, but will also include the
                            four corners of each pixel. Default value of ``4``.
        :type connectivity: :class:`numbers.Integral`
        :param diameter_threshold: Optional argument to merge any region under
                                   a given value. A region is defined as:
                                   ``sqr(4*area/pi)``. Requires
                                   ImageMagick-7.0.9-24.
        :type diameter_threshold: :class:`basestring`
        :param eccentricity_threshold: Optional argument to merge any region
                                       with ellipse eccentricity under a given
                                       value. Requires ImageMagick-7.0.9-24,
                                       or greater.
        :param keep: Comma separated list of object IDs to isolate, the reset
                     are converted to transparent.
        :type keep: :class:`basestring`
        :param keep_colors: Semicolon separated list of objects to keep by
                            their color value. Requires ImageMagick-7.0.9-24,
                            or greater.
        :type keep_colors: :class:`basestring`
        :param keep_top: Keeps only the top number of objects by area.
                         Requires ImageMagick-7.0.9-24, or greater.
        :type keep_top: :class:`basestring`
        :param major_axis_threshold: Optional argument to merge any ellipse
                                     with a major axis smaller then given
                                     value. Requires ImageMagick-7.0.9-24,
                                     or greater.
        :type major_axis_threshold: :class:`basestring`
        :param mean_color: Optional argument. Replace object color with mean
                           color of the source image.
        :type mean_color: :class:`bool`
        :param minor_axis_threshold: Optional argument to merge any ellipse
                                     with a minor axis smaller then given
                                     value. Requires ImageMagick-7.0.9-24,
                                     or greater.
        :type minor_axis_threshold: :class:`basestring`
        :param perimeter_threshold: Optional argument to merge any region with
                                    a perimeter smaller than the given value.
                                    Requires ImageMagick-7.0.9-24, or greater.
        :param remove: Comma separated list of object IDs to ignore, and
                       convert to transparent.
        :type remove: :class:`basestring`
        :param remove_colors: Semicolon separated list of objects to remove
                              by there color. Requires ImageMagick-7.0.9-24,
                              or greater.
        :type remove_colors: :class:`basestring`
        :returns: A list of :class:`ConnectedComponentObject`.
        :rtype: :class:`list` [:class:`ConnectedComponentObject`]
        :raises WandLibraryVersionError: If ImageMagick library
                                         does not support this method.

        .. versionadded:: 0.5.5

        .. versionchanged:: 0.5.6
           Added ``mean_color``, ``keep``, & ``remove`` optional arguments.

        .. versionchanged:: 0.6.4
           Added ``angle_threshold``, ``circularity_threshold``,
           ``diameter_threshold``, ``eccentricity_threshold``,
           ``keep_colors``, ``major_axis_threshold``, ``minor_axis_threshold``,
           ``perimeter_threshold``, and ``remove_colors`` optional arguments.
        angle_thresholdNarea_thresholdbackground_idcircularity_thresholdconnectivityr_   diameter_thresholdeccentricity_thresholdkeepkeep_colorskeep_topmajor_axis_threshold
mean_colorFminor_axis_thresholdperimeter_thresholdrW   remove_colorsz8Method requires ImageMagick version 7.0.8-41 or greater.)r_   r`   zconnectivity must be 4, or 8.s$   connected-components:angle-thresholds#   connected-components:area-thresholds"   connected-components:background-ids*   connected-components:circularity-thresholds'   connected-components:diameter-thresholds+   connected-components:eccentricity-thresholds   connected-components:keeps    connected-components:keep-colorss   connected-components:keep-tops)   connected-components:major-axis-thresholds   connected-components:mean-colors   trues)   connected-components:minor-axis-thresholds(   connected-components:perimeter-thresholds   connected-components:removes"   connected-components:remove-colorsr   i	  )r  r   ZMagickConnectedComponentsImager   r  r   r  r  r  c_void_pr   r   r   sizeofr  r4  r   r;  memmover   r  rJ   r   ZRelinquishMagickMemoryr  )r  r  r  r  r  r  r	  r
  r  r  r  r  r  r  r  r  rW   r  r  r  r  Zobjects_ptrZCCObjectInfoStructureZccoi_mem_sizer  objectsr)  tempZsrc_addrr  r  r  connected_components  s    w


















zBaseImage.connected_componentsTc             C   s   t j|d t| j|S )aK  Enhances the difference between lighter & darker values of the
        image. Set ``sharpen`` to ``False`` to reduce contrast.

        :param sharpen: Increase, or decrease, contrast. Default is ``True``
                        for increased contrast.
        :type sharpen: :class:`bool`

        .. versionadded:: 0.5.7
        )sharpen)r   r,  r   ZMagickContrastImager  )r  r  r  r  r  r    s    zBaseImage.contrastc             C   s   t j|d |dkr|}t j|d t| j| j }d|  k rHdkrTn n||9 }d|  k rhdkrtn n||9 }|| }|dkrt| j||}nP| |}tj	rt	| j|||}n,t
| j|}t| j||}t
| j| |S )a5  Enhance contrast of image by adjusting the span of the available
        colors.

        :param black_point: black point between 0.0 and 1.0.  default is 0.0
        :type black_point: :class:`numbers.Real`
        :param white_point: white point between 0.0 and 1.0.
                            Defaults to the same value given to the
                            ``black_point`` argument.
        :type white_point: :class:`numbers.Real`
        :param channel: optional color channel to apply contrast stretch
        :type channel: :const:`CHANNELS`
        :raises ValueError: if ``channel`` is not in :const:`CHANNELS`

        .. versionadded:: 0.4.1

        .. versionchanged:: 0.5.5
           The ``white_point`` argument will now default to the value given
           by the ``black_point`` argument.
        )black_pointN)r  g        g      ?)r   rQ  r  r  r  r   ZMagickContrastStretchImager  r  Z!MagickContrastStretchImageChannelr  )r  r  r  r  Zcontrast_ranger  r  channel_maskr  r  r  contrast_stretch  s6    
zBaseImage.contrast_stretchc          	   C   s   g }t dk rd}t||  }|dk	rbt|tr:|j}tj|d d}t|}t	
|j|| t	|jdd t	|jd t }t	|jt|}|rt||j}	t	|}|	d	d
 d}
dd |
D }n|   W dQ R X |S )a  Find the smallest convex polygon, and returns a list of points.

        .. note:: Requires ImageMagick-7.0.10 or greater.

        You can pass the list of points directly to
        :meth:`Drawing.polygon() <wand.drawing.Drawing.polygon>` method
        to draw the convex hull shape on the image.

        .. code::

            from wand.image import Image
            from wand.drawing import Drawing

            with Image(filename='kdf_black.png') as img:
              points = img.convex_hull()
              with Drawing() as ctx:
                ctx.fill_color = 'transparent'
                ctx.stroke_color = 'red'
                ctx.polygon(points=points)
                ctx(img)
            img.save(filename='kdf_black_convex_hull.png')

        .. image:: ../_images/wand/image/kdf_black.png
        .. image:: ../_images/wand/image/kdf_black_convex_hull.png

        :param background: Define which color value to evaluate as the
                           background.
        :type background: :class:`basestring` or :class:`~wand.color.Color`
        :returns: list of points
        :rtype: :class:`list` [ :class:`tuple` ( :class:`float`,
                :class:`float` ) ]

        .. versionadded:: 0.6.4
        i
  z4ImageMagick-7.0.10 is required to use convex_hull().N)rM   s   convex-hull:background-colors   formats   %[convex-hull]s   INFOasciiignore c             S   s$   g | ]}t td d |dqS )c             S   s   t | S )N)r  )r  r  r  r  <lambda>      z2BaseImage.convex_hull.<locals>.<listcomp>.<lambda>r  )r  mapsplit)r  r5  r  r  r  
<listcomp>  s    z)BaseImage.convex_hull.<locals>.<listcomp>)r   r   r  r  r   rN  r   rR  r   r   r  r  MagickSetOptionrT  r  rh  MagickGetImageBlobr  rO  r4  rP  decoderS  r$  r  )r  rM   r  r  tmpr  r  lengthblob_pblobptsr  r  r  r\    s0    #


zBaseImage.convex_hullc	             C   s  |dks|dkst dn|dks2|dks2t dddd}	|rl|dksP|dkrXt d| |||\}}n|	|| jd}|	|| jd}|dkr|	|| j}|| }|dkr|	|| j}|| }tj||d ||  krdkrn n|| jkr|| jkrd	S | jrt| j	| _	| 
  t| j	 t| j	}
t| j	 xltd|
d
 D ]6}t| j	| t| j	||||}|rV|   qVW n"t| j	||||}|r|   |S )a  Crops the image in-place.

        .. sourcecode:: text

           +--------------------------------------------------+
           |              ^                         ^         |
           |              |                         |         |
           |             top                        |         |
           |              |                         |         |
           |              v                         |         |
           | <-- left --> +-------------------+  bottom       |
           |              |             ^     |     |         |
           |              | <-- width --|---> |     |         |
           |              |           height  |     |         |
           |              |             |     |     |         |
           |              |             v     |     |         |
           |              +-------------------+     v         |
           | <--------------- right ---------->               |
           +--------------------------------------------------+

        :param left: x-offset of the cropped image. default is 0
        :type left: :class:`numbers.Integral`
        :param top: y-offset of the cropped image. default is 0
        :type top: :class:`numbers.Integral`
        :param right: second x-offset of the cropped image.
                      default is the :attr:`width` of the image.
                      this parameter and ``width`` parameter are exclusive
                      each other
        :type right: :class:`numbers.Integral`
        :param bottom: second y-offset of the cropped image.
                       default is the :attr:`height` of the image.
                       this parameter and ``height`` parameter are exclusive
                       each other
        :type bottom: :class:`numbers.Integral`
        :param width: the :attr:`width` of the cropped image.
                      default is the :attr:`width` of the image.
                      this parameter and ``right`` parameter are exclusive
                      each other
        :type width: :class:`numbers.Integral`
        :param height: the :attr:`height` of the cropped image.
                       default is the :attr:`height` of the image.
                       this parameter and ``bottom`` parameter are exclusive
                       each other
        :type height: :class:`numbers.Integral`
        :param reset_coords:
           optional flag. If set, after the rotation, the coordinate frame
           will be relocated to the upper-left corner of the new image.
           By default is `True`.
        :type reset_coords: :class:`bool`
        :param gravity: optional flag. If set, will calculate the :attr:`top`
                        and :attr:`left` attributes. This requires both
                        :attr:`width` and :attr:`height` parameters to be
                        included.
        :type gravity: :const:`GRAVITY_TYPES`
        :raises ValueError: when one or more arguments are invalid

        .. note::

           If you want to crop the image but not in-place, use slicing
           operator.

        .. versionchanged:: 0.4.1
           Added ``gravity`` option. Using ``gravity`` along with
           ``width`` & ``height`` to auto-adjust ``left`` & ``top``
           attributes.

        .. versionchanged:: 0.1.8
           Made to raise :exc:`~exceptions.ValueError` instead of
           :exc:`~exceptions.IndexError` for invalid ``width``/``height``
           arguments.

        .. versionadded:: 0.1.7

        NzFparameters right and width are exclusive each other; use one at a timezHparameters bottom and height are exclusive each other; use one at a timec             S   sj   | d kr|d kr|S |S t | tjs6tdt|  n | |krVtt| d t| | dk rf||  S | S )Nzexpected integer, not z > r   )r  r  r  r  r  r  )r(  rp  nullr  r  r  abs_r  s    zBaseImage.crop.<locals>.abs_z2both width and height must be defined with gravityr   )r  r  Tr   )N)r  r  r  r  r   assert_counting_numberr*  r   r  r  r  r$  r%  r&  r   r'  ZMagickCropImagereset_coords)r  r  r  rightbottomr  r  r1  rY  r/  r(  r)  r  r  r  r  r    sP    O


zBaseImage.cropr   c             C   s   t j|d t| j|S )zShift the image color-map by a given offset.

        :param offset: number of steps to rotate index by.
        :type offset: :class:`numbers.Integral`

        .. versionadded:: 0.5.3
        )r  )r   rA  r   ZMagickCycleColormapImager  )r  r  r  r  r  cycle_color_map  s    	zBaseImage.cycle_color_mapc             C   s   t j|d t| jt|S )aq  Decrypt ciphered pixels into original values.

        .. note::

            :class:`~wand.exceptions.ImageError` will be thrown if the system's
            ImageMagick library was compiled without cipher support.

        :param passphrase: the secret passphrase to decrypt with.
        :type passphrase: :class:`basestring`

        .. versionadded:: 0.6.3
        )
passphrase)r   rR  r   MagickDecipherImager  r	   )r  r5  r  r  r  decipher  s    zBaseImage.decipherc             C   s&   t | j}|r|| _|   t|S )zIterates over internal image stack, and adjust each frame size to
        minimum bounding region of any changes from the previous frame.

        .. versionadded:: 0.5.0
        )r   ZMagickDeconstructImagesr  r  r  )r  r  r  r  r  deconstruct  s
    zBaseImage.deconstructc             C   s<   t j|d d|  k r dkr.n n
|| j9 }t| j|S )ax  Attempts to remove skew artifacts common with most
        scanning & optical import devices.

        :params threshold: limit between foreground & background. Use a real
                           number between `0.0` & `1.0` to match CLI's percent
                           argument.
        :type threshold: :class:`numbers.Real`

        .. versionadded:: 0.5.0
        )r   r   g      ?)r   rQ  r  r   ZMagickDeskewImager  )r  r   r  r  r  deskew  s    
zBaseImage.deskewc             C   s   t | jS )z~Applies filter to reduce noise in image.

        :see: Example of :ref:`despeckle`.

        .. versionadded:: 0.5.0
        )r   ZMagickDespeckleImager  )r  r  r  r  	despeckle  s    	zBaseImage.despecklec             C   sd   t jtd|d t|tjs,tdt| t|}t	j
| | }t|}t| j|||t|S )a  Distorts an image using various distorting methods.

        .. code:: python

            from wand.image import Image
            from wand.color import Color

            with Image(filename='checks.png') as img:
                img.virtual_pixel = 'background'
                img.background_color = Color('green')
                img.matte_color = Color('skyblue')
                arguments = (0, 0, 20, 60,
                             90, 0, 70, 63,
                             0, 90, 5, 83,
                             90, 90, 85, 88)
                img.distort('perspective', arguments)
                img.save(filename='checks_perspective.png')

        .. image:: ../_images/wand/image/checks.png
        .. image:: ../_images/wand/image/checks_perspective.png

        Use :attr:`virtual_pixel`, :attr:`background_color`, and
        :attr:`matte_color` properties to control the behavior of pixels
        rendered outside of the image boundaries.

        Use :attr:`interpolate_method` to control how images scale-up.

        Distortion viewport, and scale, can be defined by using
        :attr:`Image.artifacts` dictionary. For example::

            img.artifacts['distort:viewport'] = '44x44+15+0'
            img.artifacts['distort:scale'] = '10'

        :see: Additional examples of :ref:`distort`.

        :param method: Distortion method name from :const:`DISTORTION_METHODS`
        :type method: :class:`basestring`
        :param arguments: List of distorting float arguments
                          unique to distortion method
        :type arguments: :class:`collections.abc.Sequence`
        :param best_fit: Attempt to resize resulting image fit distortion.
                         Defaults False
        :type best_fit: :class:`bool`

        .. versionadded:: 0.4.1
        zwand.image.DISTORTION_METHODS)rc  z"expected sequence of doubles, not )r   r#  r(   r  r   r8  r  r  r  r  r  rp   r   ZMagickDistortImager  r  )r  rc  r  Zbest_fitargcargvra  r  r  r  r     s    1

zBaseImage.distortc             C   s   t j|d t| j|S )zApplies convolution filter to detect edges.

        :see: Example of :ref:`edge`.

        :param radius: aperture of detection filter.
        :type radius: :class:`numbers.Real`

        .. versionadded:: 0.5.0
        )r  )r   rQ  r   ZMagickEdgeImager  )r  r  r  r  r  rs  ,  s    zBaseImage.edgec             C   s   t j||d t| j||S )a  Applies convolution filter against Gaussians filter.

        .. note::

            The `radius` value should be larger than `sigma` for best results.

        :see: Example of :ref:`emboss`.

        :param radius: filter aperture size.
        :type radius: :class:`numbers.Real`
        :param sigma: standard deviation.
        :type sigma: :class:`numbers.Real`

        .. versionadded:: 0.5.0
        )r  r  )r   rQ  r   ZMagickEmbossImager  )r  r  r  r  r  r  emboss;  s    zBaseImage.embossc             C   s   t j|d t| jt|S )an  Encrypt plain pixels into ciphered values.

        .. note::

            :class:`~wand.exceptions.ImageError` will be thrown if the system's
            ImageMagick library was compiled without cipher support.

        :param passphrase: the secret passphrase to encrypt with.
        :type passphrase: :class:`basestring`

        .. versionadded:: 0.6.3
        )r5  )r   rR  r   r6  r  r	   )r  r5  r  r  r  encipherP  s    zBaseImage.encipherc             C   s   t | jS )z{Applies digital filter to reduce noise.

        :see: Example of :ref:`enhance`.

        .. versionadded:: 0.5.0
        )r   ZMagickEnhanceImager  )r  r  r  r  enhanceb  s    	zBaseImage.enhancec             C   sd   |dkrt | j}nJ| |}tdk r8t | j|}n(t | j|}t | j}t | j| |S )a  Equalizes the image histogram

        :param channel: Optional channel. See :const:`CHANNELS`.
        :type channel: :class:`basestring`

        .. versionadded:: 0.3.10

        .. versionchanged:: 0.5.5
           Added optional ``channel`` argument.
        Ni   )r   ZMagickEqualizeImager  r  r   ZMagickEqualizeImageChannelr  )r  r  r  r  r  r  r  r  equalizem  s    
zBaseImage.equalizec             C   s   t jtd|d t j|d t|}|dkr@t| j||}nP| |}tj	rdt	| j|||}n,t
| j|}t| j||}t
| j| |S )aM  Apply arithmetic, relational, or logical expression to an image.

        Percent values must be calculated against the quantum range of the
        image::

            fifty_percent = img.quantum_range * 0.5
            img.evaluate(operator='set', value=fifty_percent)

        :see: Example of :ref:`evaluate`.

        :param operator: Type of operation to calculate
        :type operator: :const:`EVALUATE_OPS`
        :param value: Number to calculate with ``operator``
        :type value: :class:`numbers.Real`
        :param channel: Optional channel to apply operation on.
        :type channel: :const:`CHANNELS`
        :raises TypeError: When ``value`` is not numeric.
        :raises ValueError: When ``operator``, or ``channel`` are not defined
                            in constants.

        .. versionadded:: 0.4.1
        zwand.image.EVALUATE_OPS)r>  )r4  N)r   r#  r*   rQ  rp   r   ZMagickEvaluateImager  r  ZMagickEvaluateImageChannelr  )r  r>  r4  r  Zidx_opr  r  r  r  r  r  evaluate  s"    

zBaseImage.evaluateRGBAr  c             C   s  | j \}}|dkr|}|dkr"|}tj||||d tj|d tjtd|d | }d}	x$|D ]}
|
|	krbtdt|
 qbW dt	j
t	jt	jt	jt	jt	jt	jg}t|}|| }|| }|t| }||  }t| j||||t||t	|}|s|   |d| S )ac  Export pixel data from a raster image to
        a list of values.

        The ``channel_map`` tells ImageMagick which color
        channels to export, and what order they should be
        written as -- per pixel. Valid entries for
        ``channel_map`` are:

        - ``'R'`` - Red channel
        - ``'G'`` - Green channel
        - ``'B'`` - Blue channel
        - ``'A'`` - Alpha channel (``0`` is transparent)
        - ``'O'`` - Alpha channel (``0`` is opaque)
        - ``'C'`` - Cyan channel
        - ``'Y'`` - Yellow channel
        - ``'M'`` - Magenta channel
        - ``'K'`` - Black channel
        - ``'I'`` - Intensity channel (only for grayscale)
        - ``'P'`` - Padding

        See :const:`STORAGE_TYPES` for a list of valid
        ``storage`` options. This tells ImageMagick
        what type of data it should calculate & write to.
        For example; a storage type of ``'char'`` will write
        a 8-bit value between 0 ~ 255,  a storage type
        of ``'short'`` will write a 16-bit value between
        0 ~ 65535, and a ``'integer'`` will write a
        32-bit value between 0 ~ 4294967295.

        .. note::

            By default, the entire image will be exported
            as ``'char'`` storage with each pixel mapping
            Red, Green, Blue, & Alpha channels.


        :param x: horizontal starting coordinate of raster.
        :type x: :class:`numbers.Integral`
        :param y: vertical starting coordinate of raster.
        :type y: :class:`numbers.Integral`
        :param width: horizontal length of raster.
        :type width: :class:`numbers.Integral`
        :param height: vertical length of raster.
        :type height: :class:`numbers.Integral`
        :param channel_map: a string listing the channel data
                            format for each pixel.
        :type channel_map: :class:`basestring`
        :param storage: what data type each value should
                        be calculated as.
        :type storage: :class:`basestring`
        :returns: list of values.
        :rtype: :class:`collections.abc.Sequence`

        .. versionadded:: 0.5.0
        N)r  r  r  r  )r  zwand.image.STORAGE_TYPES)storageRGBAOCYMKIPzUnknown channel label: )r  r   rA  rR  r#  r:   rU  r  r  r  c_ubyter  c_floatc_uintc_ulongc_ushortrp   r  r   r  r  r	   r  r  )r  r  r  r  r  r  rC  _w_hvalid_channelsr  c_storage_typesr  Z	c_storageZtotal_pixelsZc_buffer_sizec_bufferr  r  r  r  export_pixels  sH    9



zBaseImage.export_pixelsc             C   sb   |dks|dkr| j }|dks&|dkr,| j}|dk r>tdn|dk rNtdt| j||||S )af  extends the image as defined by the geometry, gravity, and wand
        background color. Set the (x,y) offset of the geometry to move the
        original wand relative to the extended wand.

        :param width: the :attr:`width` of the extended image.
                      default is the :attr:`width` of the image.
        :type width: :class:`numbers.Integral`
        :param height: the :attr:`height` of the extended image.
                       default is the :attr:`height` of the image.
        :type height: :class:`numbers.Integral`
        :param x: the :attr:`x` offset of the extended image.
                      default is 0
        :type x: :class:`numbers.Integral`
        :param y: the :attr:`y` offset of the extended image.
                       default is 0
        :type y: :class:`numbers.Integral`

        .. versionadded:: 0.4.5
        Nr   z&image width cannot be negative integerz'image height cannot be negative integer)r  r  r  r   ZMagickExtentImager  )r  r  r  r  r  r  r  r  extent  s    
zBaseImage.extentc                s    fdd}t dk rtj}ntj}tj|d || j| i } r| j}| jr\| d|d< |dkrt| d|d< nl|dkr| d|d< | d	|d	< | d
|d
< | d|d< n*| d|d< | d|d< | d|d< t	  |S )a  Calculate directional image features for each color channel.
        Feature metrics including:

        - angular second moment
        - contrast
        - correlation
        - variance sum of squares
        - inverse difference moment
        - sum average
        - sum variance
        - sum entropy
        - entropy
        - difference variance
        - difference entropy
        - information measures of correlation 1
        - information measures of correlation 2
        - maximum correlation coefficient

        With each metric containing horizontal, vertical, left & right
        diagonal values.

        .. code::

            from wand.image import Image

            with Image(filename='rose:') as img:
                channel_features = img.features(distance=32)
                for channels, features in channel_features.items():
                    print(channels)
                    for feature, directions in features.items():
                        print('  ', feature)
                        for name, value in directions.items():
                            print('    ', name, value)

        :param distance: Define the distance if pixels to calculate.
        :type distance: :class:`numbers.Integral`
        :returns: a dict mapping each color channel with a dict of each
                  feature.
        :rtype: :class:`dict`

        .. versionadded:: 0.5.5
        c                sl   t  }t|}tt| t| |  | d}i }x.|jD ]$}|d }tt|t	||||< q@W |S )N)
horizontalverticalZleft_diagonalZright_diagonalr   )
r   r  r  r  r   r"   _fields_r  r   r  )addressr  featurer  keysZfeature_dictre  a)feature_ptrr  r  build_channelb  s    
z)BaseImage.features.<locals>.build_channeli   )rk  rm   rg   r   rh   rj   rl   ro   rf   ri   rk   )
r   r   ZMagickGetImageChannelFeaturesZMagickGetImageFeaturesr   r[  r  r  r  rP  )r  rk  rY  rc  responser  r  )rX  r  features7  s.    +
zBaseImage.featuresc             C   s
   |  |S )zVAlias for :meth:`forward_fourier_transform`.

        .. versionadded:: 0.5.7
        )forward_fourier_transform)r  r   r  r  r  fft  s    zBaseImage.fftc             C   s   t | jS )zCreates a vertical mirror image by reflecting the pixels around
        the central x-axis.  It manipulates the image in place.

        :see: Example of :ref:`flip_flop`.

        .. versionadded:: 0.3.0

        )r   ZMagickFlipImager  )r  r  r  r  r    s    zBaseImage.flipc             C   s   t | jS )zCreates a horizontal mirror image by reflecting the pixels around
        the central y-axis.  It manipulates the image in place.

        :see: Example of :ref:`flip_flop`.

        .. versionadded:: 0.3.0

        )r   ZMagickFlopImager  )r  r  r  r  r    s    zBaseImage.flopc             C   s   t j|d t| j|S )a  Performs a discrete Fourier transform. The image stack is replaced
        with the results. Either a pair of magnitude & phase images, or
        real & imaginary (HDRI).

        .. code::

            from wand.image import Image
            from wand.version import QUANTUM_RANGE

            with Image(filename='source.png') as img:
                img.forward_fourier_transform()
                img.depth = QUANTUM_RANGE
                img.save(filename='fft_%02d.png')

        .. seealso:: :meth:`inverse_fourier_transform` & :meth:`complex`

        .. note::

            ImageMagick must have HDRI support to compute real & imaginary
            components (i.e. ``magnitude=False``).

        :param magnitude: If ``True``, generate magnitude & phase, else
                          real & imaginary. Default ``True``
        :type magnitude: :class:`bool`

        .. versionadded:: 0.5.5
        )r   )r   r,  r   Z"MagickForwardFourierTransformImager  )r  r   r  r  r  r\    s    z#BaseImage.forward_fourier_transformc       	   
   C   s   |dkrt d}t|tr"t |}tj|d tj||d tj||d |\ tdk rrt	| j
|j||||}n4tjtd|d t|}t	| j
|j|||||}W dQ R X |S )	at  Creates a bordered frame around image.
        Inner & outer bevel can simulate a 3D effect.

        :param matte: color of the frame
        :type matte: :class:`wand.color.Color`
        :param width: total size of frame on x-axis
        :type width: :class:`numbers.Integral`
        :param height: total size of frame on y-axis
        :type height: :class:`numbers.Integral`
        :param inner_bevel: inset shadow length
        :type inner_bevel: :class:`numbers.Real`
        :param outer_bevel: outset highlight length
        :type outer_bevel: :class:`numbers.Real`
        :param compose: Optional composite operator. Default ``'over'``, and
                        only available with ImageMagick-7.
        :type compose: :class:`basestring`

        .. versionadded:: 0.4.1

        .. versionchanged:: 0.5.6
           Added optional ``compose`` parameter.
        Nrg   )matte)r  r  )inner_bevelouter_beveli   zwand.image.COMPOSITE_OPERATORS)r=  )r   r  r   r   r  rA  rQ  r   r   ZMagickFrameImager  r2  r#  r%   rp   )	r  r^  r  r  r_  r`  r=  r  r   r  r  r  frame  s0    


zBaseImage.framec       
      C   s   t jtd|d t|tjs,tdt| t|}t	j
| | }t|}|dkrht| j|||}nT| |}tjrt| j||||}n.t| j|}	t| j|||}t| j|	 |S )aj  Apply an arithmetic, relational, or logical expression to an image.

        Defaults entire image, but can isolate affects to single color channel
        by passing :const:`CHANNELS` value to ``channel`` parameter.

        .. note::

           Support for function methods added in the following versions
           of ImageMagick.

           - ``'polynomial'`` >= 6.4.8-8
           - ``'sinusoid'`` >= 6.4.8-8
           - ``'arcsin'`` >= 6.5.3-1
           - ``'arctan'`` >= 6.5.3-1

        :see: Example of :ref:`function`.

        :param function: a string listed in :const:`FUNCTION_TYPES`
        :type function: :class:`basestring`
        :param arguments: a sequence of doubles to apply against ``function``
        :type arguments: :class:`collections.abc.Sequence`
        :param channel: optional :const:`CHANNELS`, defaults all
        :type channel: :class:`basestring`
        :raises ValueError: when a ``function``, or ``channel`` is not
                            defined in there respected constant
        :raises TypeError: if ``arguments`` is not a sequence

        .. versionadded:: 0.4.1
        zwand.image.FUNCTION_TYPES)r  z%expecting sequence of arguments, not N)r   r#  r,   r  r   r8  r  r  r  r  r  rp   r   ZMagickFunctionImager  r  ZMagickFunctionImageChannelr  )
r  r  r  r  r;  r<  rp   r  
ch_channelr  r  r  r  r    s,     

zBaseImage.functionc             C   s   t j|d t|}|dkr,t| j|}nL| |}tjrNt| j||}n*t| j|}t| j|}t| j| |rt	t
|dS |   dS )aL  Manipulate each pixel of an image by given expression.

        FX will preserver current wand instance, and return a new instance of
        :class:`Image` containing affected pixels.

        Defaults entire image, but can isolate affects to single color channel
        by passing :const:`CHANNELS` value to ``channel`` parameter.

        .. seealso:: The anatomy of FX expressions can be found at
                     http://www.imagemagick.org/script/fx.php


        :see: Example of :ref:`fx`.

        :param expression: The entire FX expression to apply
        :type expression: :class:`basestring`
        :param channel: Optional channel to target.
        :type channel: :const:`CHANNELS`
        :returns: A new instance of an image with expression applied
        :rtype: :class:`Image`

        .. versionadded:: 0.4.1
        )
expressionN)r	  )r   rR  r	   r   ZMagickFxImager  r  ZMagickFxImageChannelr  rB   r=   r  )r  rc  r  Zc_expressionr  rb  r  r  r  r  fx9  s     
zBaseImage.fxc             C   st   t j|d |dkr$t| j|}nL| |}tjrFt| j||}n*t| j|}t| j|}t| j| |S )aZ  Gamma correct image.

        Specific color channels can be correct individual. Typical values
        range between 0.8 and 2.3.

        :see: Example of :ref:`gamma`.

        :param adjustment_value: value to adjust gamma level. Default `1.0`
        :type adjustment_value: :class:`numbers.Real`
        :param channel: optional channel to apply gamma correction
        :type channel: :class:`basestring`
        :raises TypeError: if ``gamma_point`` is not a :class:`numbers.Real`
        :raises ValueError: if ``channel`` is not in :const:`CHANNELS`

        .. versionadded:: 0.4.1

        )adjustment_valueN)r   rQ  r   ZMagickGammaImager  r  ZMagickGammaImageChannelr  )r  re  r  r  r  r  r  r  r  r  h  s    
zBaseImage.gammac             C   s~   t j||d |dkr(t| j||}nR| |}tdk rNt| j|||}n,t| j|}t| j||}t| j| |S )a  Blurs the image.  We convolve the image with a gaussian operator
        of the given ``radius`` and standard deviation (``sigma``).
        For reasonable results, the ``radius`` should be larger
        than ``sigma``.  Use a ``radius`` of 0 and :meth:`blur()` selects
        a suitable ``radius`` for you.

        :see: Example of :ref:`gaussian_blur`.

        :param radius: the radius of the, in pixels,
                       not counting the center pixel
        :type radius: :class:`numbers.Real`
        :param sigma: the standard deviation of the, in pixels
        :type sigma: :class:`numbers.Real`
        :param channel: Optional color channel to target. See
                        :const:`CHANNELS`
        :type channel: :class:`basestring`

        .. versionadded:: 0.3.3

        .. versionchanged:: 0.5.5
           Added ``channel`` argument.
        .. versionchanged:: 0.5.7
           Positional arguments ``radius`` & ``sigma`` have been converted
           to keyword arguments.
        )r  r  Ni   )	r   rQ  r   ZMagickGaussianBlurImager  r  r   ZMagickGaussianBlurImageChannelr  )r  r  r  r  r  r  r  r  r  r  gaussian_blur  s    
zBaseImage.gaussian_blurc             C   sd   t |tstdt| tjtd|d t|}t	d}t
| j|j||}|s^|   |jS )a@  Compares two images, and return the specified distortion metric.

        This method is faster than :meth:`compare()` method as ImageMagick
        will not need to reconstruct an image.

        :param image: Image to reference.
        :type image: :class:`wand.image.BaseImage`
        :param metric: Compare disortion metric to use. See
                       :const:`COMPARE_METRICS`.
        :type metric: :class:`basestring`
        :returns: Computed value of the distortion metric used.
        :rtype: :class:`numbers.Real`

        .. versionadded:: 0.6.6
        zexpecting a base image, not zwand.image.COMPARE_METRICS)r  g        )r  r=   r  r  r   r#  r$   rp   r  r  r   ZMagickGetImageDistortionr  r  r4  )r  r	  r  
metric_idxdistokr  r  r  get_image_distortion  s    


zBaseImage.get_image_distortionc             C   s   t |tstdt| |dkr4t| j|j}nR| |}tdk rZt	| j||j}n,t
| j|}t| j|j}t
| j| |S )a  Replace color values by referencing a Higher And Lower Dimension
        (HALD) Color Look Up Table (CLUT). You can generate a HALD image
        by using ImageMagick's `hald:` protocol. ::

            with Image(filename='rose:') as img:
                with Image(filename='hald:3') as hald:
                    hald.gamma(1.367)
                    img.hald_clut(hald)

        :param image: The HALD color matrix.
        :type image: :class:`wand.image.BaseImage`
        :param channel: Optional color channel to target. See
                        :const:`CHANNELS`
        :type channel: :class:`basestring`

        .. versionadded:: 0.5.0

        .. versionchanged:: 0.5.5
           Added ``channel`` argument.
        zexpecting a base image, not Ni   )r  r=   r  r  r   ZMagickHaldClutImager  r  r   ZMagickHaldClutImageChannelr  )r  r	  r  r  r  r  r  r  r  	hald_clut  s    



zBaseImage.hald_clut(   c             C   sD   t jdkrd}t||dkr"|}tj|||d t | j|||S )a  Identify lines within an image. Use :meth:`canny` to reduce image
        to a binary edge before calling this method.

        .. warning::

            This class method is only available with ImageMagick 7.0.8-41, or
            greater.

        :param width: Local maxima of neighboring pixels.
        :type width: :class:`numbers.Integral`
        :param height: Local maxima of neighboring pixels.
        :type height: :class:`numbers.Integral`
        :param threshold: Line count to limit. Default to 40.
        :type threshold: :class:`numbers.Integral`
        :raises WandLibraryVersionError: If system's version of ImageMagick
                                         does not support this method.

        .. versionadded:: 0.5.5
        Nz8Method requires ImageMagick version 7.0.8-41 or greater.)r  r  r   )r   ZMagickHoughLineImager   r   r[  r  )r  r  r  r   r  r  r  r  hough_lines  s    
zBaseImage.hough_linesc             C   s   |  ||S )zVAlias for :meth:`inverse_fourier_transform`.

        .. versionadded:: 0.5.7
        )inverse_fourier_transform)r  phaser   r  r  r  ift  s    zBaseImage.iftc             C   sR   t j|d t jtd|d tdk r4t| j|}nt|}t| j||}|S )a(  Creates a "imploding" effect by pulling pixels towards the center
        of the image.

        :see: Example of :ref:`implode`.

        :param amount: Normalized degree of effect between `0.0` & `1.0`.
        :type amount: :class:`numbers.Real`
        :param method: Which interpolate method to apply to effected pixels.
                       See :const:`PIXEL_INTERPOLATE_METHODS` for a list of
                       options. Only available with ImageMagick-7.
        :type method: :class:`basestring`

        .. versionadded:: 0.5.2
        )amountz$wand.image.PIXEL_INTERPOLATE_METHODS)rc  i   )	r   rQ  r#  r6   r   r   ZMagickImplodeImager  rp   )r  rq  rc  r  ra  r  r  r  implode$  s    
zBaseImage.imploder  c             C   s>  | j \}}	|dkr|}|dkr"|	}tj||||d tjtd|d tj|d | }d}
x$|D ]}||
krbtdt| qbW t	|t
jstdt| || t| }t|}||krd	||}t|dtjtjtjtjtjtjtjg}t|}|| }t|| | }t| j||||t||t|}|S )
a_  Import pixel data from a byte-string to
        the image. The instance of :class:`Image` must already
        be allocated with the correct size.

        The ``channel_map`` tells ImageMagick which color
        channels to export, and what order they should be
        written as -- per pixel. Valid entries for
        ``channel_map`` are:

        - ``'R'`` - Red channel
        - ``'G'`` - Green channel
        - ``'B'`` - Blue channel
        - ``'A'`` - Alpha channel (``0`` is transparent)
        - ``'O'`` - Alpha channel (``0`` is opaque)
        - ``'C'`` - Cyan channel
        - ``'Y'`` - Yellow channel
        - ``'M'`` - Magenta channel
        - ``'K'`` - Black channel
        - ``'I'`` - Intensity channel (only for grayscale)
        - ``'P'`` - Padding

        See :const:`STORAGE_TYPES` for a list of valid
        ``storage`` options. This tells ImageMagick
        what type of data it should calculate & write to.
        For example; a storage type of ``'char'`` will write
        a 8-bit value between 0 ~ 255,  a storage type
        of ``'short'`` will write a 16-bit value between
        0 ~ 65535, and a ``'integer'`` will write a
        32-bit value between 0 ~ 4294967295.

        .. note::

            By default, the entire image will be exported
            as ``'char'`` storage with each pixel mapping
            Red, Green, Blue, & Alpha channels.


        :param x: horizontal starting coordinate of raster.
        :type x: :class:`numbers.Integral`
        :param y: vertical starting coordinate of raster.
        :type y: :class:`numbers.Integral`
        :param width: horizontal length of raster.
        :type width: :class:`numbers.Integral`
        :param height: vertical length of raster.
        :type height: :class:`numbers.Integral`
        :param channel_map: a string listing the channel data
                            format for each pixel.
        :type channel_map: :class:`basestring`
        :param storage: what data type each value should
                        be calculated as.
        :type storage: :class:`basestring`

        .. versionadded:: 0.5.0
        N)r  r  r  r  zwand.image.STORAGE_TYPES)rC  )r  rD  zUnknown channel label: zdata must list of values, notz#data length should be {0}, not {1}.)r  r   rA  r#  r:   rR  rU  r  r  r  r   r8  r  r  r  r  rE  r  rF  rG  rH  rI  rp   r   r  r  r	   r  )r  r  r  r  r  r  rC  r  rJ  rK  rL  r  expected_lenZ	given_lenr  rM  r  Zc_typerN  r  r  r  r  import_pixels?  sT    9


zBaseImage.import_pixelsc             C   s8   t |tstdt| tj|d t| j|j|S )a.  Applies the inverse of a discrete Fourier transform. The image stack
        is replaced with the results. Either a pair of magnitude & phase
        images, or real & imaginary (HDRI).

        .. code::

            from wand.image import Image

            with Image(filename='magnitude.png') as img:
                with Image(filename='phase.png') as phase:
                    img.inverse_fourier_transform(phase)
                img.save(filename='output.png')

        .. seealso:: :meth:`forward_fourier_transform` & :meth:`complex`

        .. note::

            ImageMagick must have HDRI support to compute real & imaginary
            components (i.e. ``magnitude=False``).

        :param phase: Second part (image) of the transform. Either the phase,
                      or the imaginary part.
        :type phase: :class:`BaseImage`
        :param magnitude: If ``True``, accept magnitude & phase input, else
                          real & imaginary. Default ``True``
        :type magnitude: :class:`bool`

        .. versionadded:: 0.5.5
        zphase must be an image, not )r   )	r  r=   r  r  r   r,  r   Z"MagickInverseFourierTransformImager  )r  ro  r   r  r  r  rn    s    
z#BaseImage.inverse_fourier_transformc             C   s   t | j dS )zSets the internal image-stack iterator to the first image.
        Useful for prepending an image at the start of the stack.

        .. versionadded:: 0.6.2
        N)r   ZMagickSetFirstIteratorr  )r  r  r  r  iterator_first  s    zBaseImage.iterator_firstc             C   s   t | jS )zReturns the position of the internal image-stack index.

        :rtype: :class:`int`

        .. versionadded:: 0.6.2
        )r   r%  r  )r  r  r  r  iterator_get  s    zBaseImage.iterator_getc             C   s   t | j dS )zSets the internal image-stack iterator to the last image.
        Useful for appending an image to the end of the stack.

        .. versionadded:: 0.6.2
        N)r   r$  r  )r  r  r  r  iterator_last  s    zBaseImage.iterator_lastc             C   s   t | jS )zsGet the count of images in the image-stack.

        :rtype: :class:`int`

        .. versionadded:: 0.6.2
        )r   r.  r  )r  r  r  r  iterator_length  s    zBaseImage.iterator_lengthc             C   s2   t | j}|r.t | j}t | j|d }|S )zsSteps the image-stack index forward by one

        :rtype: :class:`bool`

        .. versionadded:: 0.6.2
        r   )r   ZMagickHasNextImager  r%  r'  )r  Zhas_nextr  r  r  r  iterator_next  s
    zBaseImage.iterator_nextc             C   s2   t | j}|r.t | j}t | j|d }|S )zqSteps the image-stack index back by one.

        :rtype: :class:`bool`

        .. versionadded:: 0.6.2
        r   )r   ZMagickHasPreviousImager  r%  r'  )r  Zhas_prevr  r  r  r  iterator_previous  s
    zBaseImage.iterator_previousc             C   s   t | j dS )zReset internal image-stack iterator. Useful for iterating over the
        image-stack without allocating :class:`~wand.sequence.Sequence`.

        .. versionadded:: 0.6.2
        N)r   r&  r  )r  r  r  r  iterator_reset	  s    zBaseImage.iterator_resetc             C   s   t j|d t| j|S )ztSets the index of the internal image-stack.

        :rtype: :class:`bool`

        .. versionadded:: 0.6.2
        )rp   )r   rA  r   r'  r  )r  rp   r  r  r  iterator_set  s    zBaseImage.iterator_setd   {Gz?c             C   sJ   t dk stjdkrd}t|tj||d tj|d t| j|||S )a  Reduces the number of colors in an image by appling the K-means
        clustering algorithm.

        .. note::

            Requires ImageMagick-7.0.10-37, or later.

        :param number_colors: the target number of colors to use as seeds.
        :type number_colors: :class:`numbers.Integral`
        :param max_iterations: maximum number of iterations needed until
                               convergence. Default ``100``.
        :type max_iterations: :class:`numbers.Integral`
        :param tolerance: maximum tolerance between distrotion iterations.
                          Default ``0.01``
        :type tolerance: :class:`numbers.Real`

        .. versionadded:: 0.6.4
        i
  Nz/Kmeans requires ImageMagick-7.0.10-37 or later.)number_colorsmax_iterations)	tolerance)r   r   ZMagickKmeansImager   r   r[  rQ  r  )r  r  r  r  r  r  r  r  kmeans  s    
zBaseImage.kmeansrx   c             C   s   |  |}td}td}tdk rFt| j|t|t| n8t| j|}t	| jt|t| t| j| |j
|j
fS )aE  Calculates the kurtosis and skewness of the image.

        .. code:: python

            from wand.image import Image

            with Image(filename='input.jpg') as img:
                kurtosis, skewness = img.kurtosis_channel()

        :param channel: Select which color channel to evaluate. See
                        :const:`CHANNELS`. Default ``'default_channels'``.
        :type channel: :class:`basestring`
        :returns: Tuple of :attr:`kurtosis` & :attr:`skewness`
                  values.
        :rtype: :class:`tuple`

        .. versionadded:: 0.5.3
        g        i   )r  r  r  r   r   ZMagickGetImageChannelKurtosisr  r  r  ZMagickGetImageKurtosisr4  )r  r  rb  re  r  r  r  r  r  rd  9  s    



zBaseImage.kurtosis_channelc             C   sD   t jdkrd}t||dkr&|d }tj||d t | j||S )a  Edge preserving noise reduction filter.

        https://en.wikipedia.org/wiki/Kuwahara_filter

        If ``sigma`` is not given, the value will be calculated as:

            sigma = radius - 0.5

        To match original algorithm's behavior, increase ``radius`` value by
        one:

            myImage.kuwahara(myRadius + 1, mySigma)

        .. warning::

            This class method is only available with ImageMagick 7.0.8-41, or
            greater.

        :see: Example of :ref:`kuwahara`.

        :param radius: Size of the filter aperture.
        :type radius: :class:`numbers.Real`
        :param sigma: Standard deviation of Gaussian filter.
        :type sigma: :class:`numbers.Real`
        :raises WandLibraryVersionError: If system's version of ImageMagick
                                         does not support this method.

        .. versionadded:: 0.5.5
        Nz8Method requires ImageMagick version 7.0.8-41 or greater.g      ?)r  r  )r   ZMagickKuwaharaImager   r   rQ  r  )r  r  r  r  r  r  r  kuwahara^  s     
zBaseImage.kuwaharac       
      C   s   t j|d |dkrd| }t j||d t| j| }t| j| }trZ|d8 }|d8 }|dkrvt| j|||}nT| |}tj	rt	| j||||}n.t
| j|}	t| j|||}t
| j|	 |S )a  Adjusts the levels of an image by scaling the colors falling
        between specified black and white points to the full available
        quantum range.

        If only ``black`` is given, ``white`` will be adjusted inward.

        :see: Example of :ref:`level`.

        :param black: Black point, as a percentage of the system's quantum
                      range. Defaults to 0.
        :type black: :class:`numbers.Real`
        :param white: White point, as a percentage of the system's quantum
                      range. Defaults to 1.0.
        :type white: :class:`numbers.Real`
        :param gamma: Optional gamma adjustment. Values > 1.0 lighten the
                      image's midtones while values < 1.0 darken them.
        :type gamma: :class:`numbers.Real`
        :param channel: The channel type. Available values can be found
                        in the :const:`CHANNELS` mapping. If ``None``,
                        normalize all channels.
        :type channel: :const:`CHANNELS`

        .. note::
            Images may not be affected if the ``white`` value is equal to or
            less than the ``black`` value.

        .. versionadded:: 0.4.1

        )ro   Ng      ?)r  r  g      ?)r   rQ  r  r  r   r   ZMagickLevelImager  r  ZMagickLevelImageChannelr  )
r  ro   r  r  r  bpZwpr  r  r  r  r  r  level  s.    
zBaseImage.levelc          
   C   s   t jdkrd}t|t|tr(t|}t|tr:t|}tj||d d}|dk	rl| |}t 	| j
|}|, | t | j
|j|jd}W dQ R X W dQ R X |dk	rt 	| j
| |S )a  Maps given colors to "black" & "white" values.

        .. warning::

            This class method is only available with ImageMagick 7.0.8-54, or
            greater.

        :param black_color: linearly map given color as "black" point.
        :type black_color: :class:`Color`
        :param white_color: linearly map given color as "white" point.
        :type white_color: :class:`Color`
        :param channel: target a specific color-channel to levelize.
        :type channel: :class:`basestring`
        :raises WandLibraryVersionError: If system's version of ImageMagick
                                         does not support this method.

        .. versionadded:: 0.5.6
        Nz8Method requires ImageMagick version 7.0.8-54 or greater.)black_colorwhite_colorF)r   MagickLevelImageColorsr   r  r   r   r   r  r  r  r  r2  )r  r  r  r  r  r  r  r  r  r  r  level_colors  s.    



zBaseImage.level_colorsc       	      C   s   t jdkrd}t||dkr(t| j}tj|||d d|  k rLdkrZn n
|| j9 }d|  k rndkr|n n
|| j9 }|dkrt | j|||}n8| |}t 	| j|}t | j|||}t 	| j| |S )a  Reverse of :meth:`level()`, this method compresses the range of
        colors between ``black`` & ``white`` values.

        If only ``black`` is given, ``white`` will be adjusted inward.

        .. warning::

            This class method is only available with ImageMagick 7.0.8-41, or
            greater.

        :param black: Black point, as a percentage of the system's quantum
                      range. Defaults to 0.
        :type black: :class:`numbers.Real`
        :param white: White point, as a percentage of the system's quantum
                      range. Defaults to 1.0.
        :type white: :class:`numbers.Real`
        :param gamma: Optional gamma adjustment. Values > 1.0 lighten the
                      image's midtones while values < 1.0 darken them.
        :type gamma: :class:`numbers.Real`
        :param channel: The channel type. Available values can be found
                        in the :const:`CHANNELS` mapping. If ``None``,
                        normalize all channels.
        :type channel: :const:`CHANNELS`
        :raises WandLibraryVersionError: If system's version of ImageMagick
                                         does not support this method.

        .. versionadded:: 0.5.5
        Nz8Method requires ImageMagick version 7.0.8-41 or greater.)ro   r  r  r   g      ?)
r   ZMagickLevelizeImager   r  r  r   rQ  r  r  r  )	r  ro   r  r  r  r  r  r  r  r  r  r  levelize  s$    




zBaseImage.levelizec          
   C   s   t jdkrd}t|t|tr(t|}t|tr:t|}tj||d d}d}|dk	rp| |}t 	| j
|}|, | t | j
|j|jd}W dQ R X W dQ R X |dk	rt 	| j
| |S )a
  Reverse of :meth:`level_colors()`, and creates a de-contrasting
        gradient of given colors. This works best with grayscale images.

        .. warning::

            This class method is only available with ImageMagick 7.0.8-54, or
            greater.

        :param black_color: tint map given color as "black" point.
        :type black_color: :class:`Color`
        :param white_color: tint map given color as "white" point.
        :type white_color: :class:`Color`
        :param channel: target a specific color-channel to levelize.
        :type channel: :class:`basestring`
        :raises WandLibraryVersionError: If system's version of ImageMagick
                                         does not support this method.

        .. versionadded:: 0.5.6
        Nz8Method requires ImageMagick version 7.0.8-54 or greater.)r  r  T)r   r  r   r  r   r   r   r  r  r  r  r2  )r  r  r  r  r  r  r  r  r  r  r  levelize_colors#  s0    



zBaseImage.levelize_colorsc             C   s6   t j||d t| j| j }t| j|| || S )aH  Enhance saturation intensity of an image.

        :param black_point: Black point between 0.0 and 1.0. Default 0.0
        :type black_point: :class:`numbers.Real`
        :param white_point: White point between 0.0 and 1.0. Default 1.0
        :type white_point: :class:`numbers.Real`

        .. versionadded:: 0.4.1
        )r  r  )r   rQ  r  r  r  r   ZMagickLinearStretchImager  )r  r  r  Zlinear_ranger  r  r  linear_stretchR  s    zBaseImage.linear_stretchc          
   C   st   t j||d t j||d t| j|||| y|   W n2 tk
rn } ztt|d W dd}~X Y nX dS )a  Rescales the image with `seam carving`_, also known as
        image retargeting, content-aware resizing, or liquid rescaling.

        :param width: the width in the scaled image
        :type width: :class:`numbers.Integral`
        :param height: the height in the scaled image
        :type height: :class:`numbers.Integral`
        :param delta_x: maximum seam transversal step.
                        0 means straight seams.  default is 0
        :type delta_x: :class:`numbers.Real`
        :param rigidity: introduce a bias for non-straight seams.
                         default is 0
        :type rigidity: :class:`numbers.Real`
        :raises wand.exceptions.MissingDelegateError:
           when ImageMagick isn't configured ``--with-lqr`` option.

        .. note::

           This feature requires ImageMagick to be configured
           ``--with-lqr`` option.  Or it will raise
           :exc:`~wand.exceptions.MissingDelegateError`:

        .. seealso::

           `Seam carving`_ --- Wikipedia
              The article which explains what seam carving is
              on Wikipedia.

        .. _Seam carving: http://en.wikipedia.org/wiki/Seam_carving

        )r  r  )delta_xrigidityz

ImageMagick in the system is likely to be impossible to load liblqr.  You might not install liblqr, or ImageMagick may not compiled with liblqr.N)	r   rA  rQ  r   ZMagickLiquidRescaleImager  r  r   r  )r  r  r  r  r  r  r  r  r  liquid_rescalee  s    !zBaseImage.liquid_rescale
         )@c             C   s4   t jdkrd}t|tj||d t | j||S )aH  Increase light-dark transitions within image.

        .. warning::

            This class method is only available with ImageMagick 6.9.3, or
            greater.

        :param radius: The size of the Gaussian operator. Default value is
                       ``10.0``.
        :type radius: :class:`numbers.Real`
        :param strength: Percentage of blur mask to apply. Values can be
                         between ``0.0`` and ``100`` with a default of
                         ``12.5``.
        :type strength: :class:`numbers.Real`

        .. versionadded:: 0.5.7
        Nz5Method requires ImageMagick version 6.9.3 or greater.)r  strength)r   ZMagickLocalContrastImager   r   rQ  r  )r  r  r  r  r  r  r  local_contrast  s
    
zBaseImage.local_contrastc             C   s   t | jS )zQuickly double an image in size. This is a convenience method.
        Use :meth:`resize()`, :meth:`resample()`, or :meth:`sample()` for
        more control.

        .. versionadded:: 0.5.5
        )r   ZMagickMagnifyImager  )r  r  r  r  magnify  s    	zBaseImage.magnifyc             C   s   |  |}td}td}tdk rFt| j|t|t| n8t| j|}t	| jt|t| t| j| |j
|j
fS )a  Calculates the mean and standard deviation of the image.

        .. code:: python

            from wand.image import Image

            with Image(filename='input.jpg') as img:
                mean, stddev = img.mean_channel()

        :param channel: Select which color channel to evaluate. See
                        :const:`CHANNELS`. Default ``'default_channels'``.
        :type channel: :class:`basestring`
        :returns: Tuple of :attr:`mean` & :attr:`standard_deviation`
                  values. The ``mean`` value will be between 0.0 &
                  :attr:`quantum_range`
        :rtype: :class:`tuple`

        .. versionadded:: 0.5.3
        g        i   )r  r  r  r   r   ZMagickGetImageChannelMeanr  r  r  ZMagickGetImageMeanr4  )r  r  rb  rp  r  r  r  r  r  ro    s    



zBaseImage.mean_channelc             C   sd   t jdkrd}t|tj||d tj|d d|  k rDdkrRn n
|| j9 }t | j|||S )aV  Recalculates pixel value by comparing neighboring pixels within a
        color distance, and replacing with a mean value. Works best with
        Gray, YCbCr, YIQ, or YUV colorspaces.

        .. warning::

            This class method is only available with ImageMagick 7.0.8-41, or
            greater.

        :param width: Size of the neighborhood window in pixels.
        :type width: :class:`numbers.Integral`
        :param height: Size of the neighborhood window in pixels.
        :type height: :class:`numbers.Integral`
        :param color_distance: Include pixel values within this color distance.
        :type color_distance: :class:`numbers.Real`
        :raises WandLibraryVersionError: If system's version of ImageMagick
                                         does not support this method.

        .. versionadded:: 0.5.5
        Nz8Method requires ImageMagick version 7.0.8-41 or greater.)r  r  )color_distancer   g      ?)r   ZMagickMeanShiftImager   r   r0  rQ  r  r  )r  r  r  r  r  r  r  r  
mean_shift  s    

zBaseImage.mean_shiftc             C   sN   t j|d |dkrtdt|}t| j|}|rF|| _|   t	|S )a  Composes all the image layers from the current given image onward
        to produce a single image of the merged layers.

        The initial canvas's size depends on the given ImageLayerMethod, and is
        initialized using the first images background color.  The images
        are then composited onto that image in sequence using the given
        composition that has been assigned to each individual image.
        The method must be set with a value from :const:`IMAGE_LAYER_METHOD`
        that is acceptable to this operation. (See ImageMagick documentation
        for more details.)

        :param method: the method of selecting the size of the initial canvas.
        :type method: :class:`basestring`

        .. versionadded:: 0.4.3

        )rc  )r7  rV   r8  r9  z@method can only be 'merge', 'flatten', 'mosaic', or 'trimbounds')
r   rR  r  r.   rp   r   ZMagickMergeImageLayersr  r  r  )r  rc  rp  r  r  r  r  merge_layers  s    
zBaseImage.merge_layersc          	   C   st  i }t dk rd}t||  H}|dk	rl|dkrPd}|dt| 7 }t|d}t|}t|j|| d}|d	7 }|d
7 }|d7 }|d7 }|d7 }t	|jd| t
|jd t }t|jt|}	|	r^t|	|j}
t|	}	|
ddd}|d  d}dd |D }ttdd |dd }dddddg}tt|||d}n|   W dQ R X |S )u  Find the minmum bounding box within the image. Use
        properties :attr:`fuzz` & :attr:`background_color` to influence
        bounding box thresholds.

        .. code::

            from wand.image import Image
            from wand.drawing import Drawing

            with Image(filename='kdf_black.png') as img:
                img.fuzz = img.quantum_range * 0.1
                img.background_color = 'black'
                mbr = img.minimum_bounding_box()
                with Drawing() as ctx:
                    ctx.fill_color = 'transparent'
                    ctx.stroke_color = 'red'
                    ctx.polygon(points=mbr['points'])
                    ctx.fill_color = 'red'
                    ctx.stroke_color = 'transparent'
                    ctx.text(1, 10, '{0:.4g}°'.format(mbr['angle']))
                    ctx(img)
                img.save(filename='kdf_black_mbr.png')

        .. image:: ../_images/wand/image/kdf_black.png
        .. image:: ../_images/wand/image/kdf_black_mbr.png

        .. note::

            Requires ImageMagick-7.0.10 or later.

        :param orientation: sets the image orientation. Values can be
                            ``'landscape'``, or ``'portrait'``.
        :type orientation: :class:`basestring`
        :returns: a directory of MBR properties & corner points.
        :rtype: :class:`dict` { "points": :class:`list` [ :class:`tuple` (
                :class:`float`, :class:`float` ) ], "area": :class:`float`,
                "width": :class:`float`, "height": :class:`float`,
                "angle": :class:`float`, "unrotate": :class:`float` }

        .. versionadded:: 0.6.4
        i
  z4ImageMagick-7.0.10 is required to use convex_hull().N)Z	landscapeZportraitz3orientation can only be landscape, or portrait, notr   s    minimum-bounding-box:orientations   %[minimum-bounding-box]s   |%[minimum-bounding-box:area]s   |%[minimum-bounding-box:width]s   |%[minimum-bounding-box:height]s   |%[minimum-bounding-box:angle]s!   |%[minimum-bounding-box:unrotate]s   formats   INFOr  r  |r   c             S   s$   g | ]}t td d |dqS )c             S   s   t | S )N)r  )r  r  r  r  r!  e  r"  z;BaseImage.minimum_bounding_box.<locals>.<listcomp>.<lambda>r  )r  r#  r$  )r  r5  r  r  r  r%  e  s    z2BaseImage.minimum_bounding_box.<locals>.<listcomp>c             S   s   t |  S )N)r  rS  )r  r  r  r  r!  f  r"  z0BaseImage.minimum_bounding_box.<locals>.<lambda>r   arear  r  r  Zunrotate)Zpoints)r   r   r  r  r  r   r   r  r  r&  rT  r  rh  r'  r  rO  r4  rP  r(  r$  rS  r  r#  r  r   r  )r  rr  r  r  r)  r  r  Zmbr_strr*  r+  r,  partsr-  attrrV  r  r  r  minimum_bounding_box  sF    *
zBaseImage.minimum_bounding_boxc             C   s   |dkr|}|  d|| dS )a  Replace each pixel with the mathematical mode of the neighboring
        colors. This is an alias of the :meth:`statistic` method.

        :param width: Number of neighboring pixels to include in mode.
        :type width: :class:`numbers.Integral`
        :param height: Optional height of neighboring pixels, defaults to the
                       same value as ``width``.
        :type height: :class:`numbers.Integral`

        .. versionadded:: 0.5.4
        Nr  )	statistic)r  r  r  r  r  r  r  m  s    zBaseImage.mode      Y@c             C   s"   t j|||d t| j|||S )a'  Changes the brightness, saturation and hue of an image.
        We modulate the image with the given ``brightness``, ``saturation``
        and ``hue``.

        :param brightness: percentage of brightness
        :type brightness: :class:`numbers.Real`
        :param saturation: percentage of saturation
        :type saturation: :class:`numbers.Real`
        :param hue: percentage of hue rotation
        :type hue: :class:`numbers.Real`
        :raises ValueError: when one or more arguments are invalid

        .. versionadded:: 0.3.4

        )r  r  r   )r   rQ  r   ZMagickModulateImager  )r  r  r  r   r  r  r  r   ~  s    zBaseImage.modulatec             C   s  t j||d t j|d d}d}|d}|d tkrT|d }t|dkrT|d }t }|rt|}	t	 }
t
t|t|
}|d	kr||
j@ dkrd
|
_n:|dkr||
j@ dkrd
|
_n|dkr||
j@ dkrd
|
_n|dkrp||
j@ dkr|
j|
_|
jd
k rd|
_|
jd
k r.|
j|
_||
j@ dkrN|
jd
 d |
_||
j@ dkr|
jd
 d |
_nr|dkr||
j@ dkrd|
_nP||
j@ dkrt| j|
jd
  |
_n(||
j@ dkr|
 jt| jd 9  _tdk r t|	t|
}nt|	t|
|}n0|rFtdk r6tt|}ntt||}d}t|}|rt|}|dkrt | j!|||}nX| "|}tdk rt#| j!||||}n.t$| j!|}t | j!|||}t$| j!| t%|}nt&dt'| |S )a	  Manipulate pixels based on the shape of neighboring pixels.

        The ``method`` determines what type of effect to apply to matching
        ``kernel`` shapes. Common methods can be add/remove,
        or lighten/darken pixel values.

        The ``kernel`` describes the shape of the matching neighbors. Common
        shapes are provided as "built-in" kernels. See
        :const`KERNEL_INFO_TYPES` for examples. The format for built-in kernels
        is:

        .. sourcecode:: text

            label:geometry

        Where `label` is the kernel name defined in :const:`KERNEL_INFO_TYPES`,
        and `:geometry` is an optional geometry size. For example::

            with Image(filename='rose:') as img:
                img.morphology(method='dilate', kernel='octagon:3x3')
                # or simply
                img.morphology(method='edgein', kernel='octagon')

        Custom kernels can be applied by following a similar format:

        .. sourcecode:: text

            geometry:args

        Where `geometry` is the size of the custom kernel, and `args`
        list a comma separated list of values. For example::

            custom_kernel='5x3:nan,1,1,1,nan 1,1,1,1,1 nan,1,1,1,nan'
            with Image(filename='rose:') as img:
                img.morphology(method='dilate', kernel=custom_kernel)

        :param method: effect function to apply. See
                       :const:`MORPHOLOGY_METHODS` for a list of
                       methods.
        :type method: :class:`basestring`
        :param kernel: shape to evaluate surrounding pixels. See
                       :const:`KERNEL_INFO_TYPES` for a list of
                       built-in shapes.
        :type kernel: :class:`basestring`
        :param iterations: Number of times a morphology method should be
                           applied to the image. Default ``1``. Use ``-1`` for
                           unlimited iterations until the image is unchanged
                           by the method operator.
        :type iterations: :class:`numbers.Integral`
        :param channel: Optional color channel to target. See
                        :const:`CHANNELS`
        :type channel: `basestring`

        .. versionadded:: 0.5.0

        .. versionchanged:: 0.5.5
           Added ``channel`` argument.
        )rc  r  )rk  N :r   r^   r   )rD  g      ?)rO  rN  rQ  rR  r   rS  )rT  )rP  g      @g       @)r_  r`  ra  rb  g      Y@i   z Unable to parse kernel info for )(r   rR  rA  r$  r1   r  r   r  rp   r   r  r	   r  r  ZRhoValuer  r  r  ZXiValuexiZPsiValuepsiZAspectValuer  r  ZPercentValuer   ZAcquireKernelBuiltInr  r  r2   r   ZMagickMorphologyImager  r  ZMagickMorphologyImageChannelr  r  r  r  )r  rc  r  rk  r  Zbuitinr  r  r  Z
kernel_idxr  r  r  r  ra  r  r  r  r  r  
morphology  s    =
















zBaseImage.morphologyc             C   s   t j|||d |dkr,t| j|||}nV| |}tdk rTt| j||||}n.t| j|}t| j|||}t| j| |S )a  Apply a Gaussian blur along an ``angle`` direction. This
        simulates motion movement.

        :see: Example of :ref:`motion_blur`.

        :param radius: Aperture size of the Gaussian operator.
        :type radius: :class:`numbers.Real`
        :param sigma: Standard deviation of the Gaussian operator.
        :type sigma: :class:`numbers.Real`
        :param angle: Apply the effect along this angle.
        :type angle: :class:`numbers.Real`

        .. versionadded:: 0.5.4
        )r  r  r  Ni   )	r   rQ  r   ZMagickMotionBlurImager  r  r   ZMagickMotionBlurImageChannelr  )r  r  r  r  r  r  r  r  r  r  r  motion_blur3  s     
zBaseImage.motion_blurc             C   sh   |dkrt | j|}nL| |}t jr:t | j||}n*t | j|}t | j|}t | j| |S )a  Negate the colors in the reference image.

        :param grayscale: if set, only negate grayscale pixels in the image.
        :type grayscale: :class:`bool`
        :param channel: the channel type.  available values can be found
                        in the :const:`CHANNELS` mapping.  If ``None``,
                        negate all channels.
        :type channel: :class:`basestring`

        .. versionadded:: 0.3.8

        N)r   ZMagickNegateImager  r  ZMagickNegateImageChannelr  )r  r;  r  r  r  r  r  r  r  negateY  s    

zBaseImage.negater{  c             C   s   t jtd|d t j|d t|}tdk rb|dkrFt| j|}q| 	|}t
| j||}nP|dkr|t| j||}n6| 	|}t| j|}t| j||}t| j| |S )a  Adds noise to image.

        :see: Example of :ref:`noise`.

        :param noise_type: type of noise to apply. See :const:`NOISE_TYPES`.
        :type noise_type: :class:`basestring`
        :param attenuate: rate of distribution. Only available in
                          ImageMagick-7. Default is ``1.0``.
        :type attenuate: :class:`numbers.Real`
        :param channel: Optionally target a color channel to apply noise to.
                        See :const:`CHANNELS`.
        :type channel: :class:`basestring`

        .. versionadded:: 0.5.3

        .. versionchanged:: 0.5.5
           Added optional ``channel`` argument.
        zwand.image.NOISE_TYPES)
noise_type)	attenuatei   N)r   r#  r3   rQ  rp   r   r   ZMagickAddNoiseImager  r  ZMagickAddNoiseImageChannelr  )r  r  r  r  Znoise_type_idxr  r  r  r  r  r  noisex  s*    




zBaseImage.noisec          	   C   s   |dkrt | j}n| |}t jr6t | j|}ndt| dT}t |j|}t |j}t |j| td| }t 	| j|j|ddd W dQ R X |S )a  Normalize color channels.

        :param channel: the channel type.  available values can be found
                        in the :const:`CHANNELS` mapping.  If ``None``,
                        normalize all channels.
        :type channel: :class:`basestring`

        N)r	  Zcopy_Fr   )
r   ZMagickNormalizeImager  r  ZMagickNormalizeImageChannelrB   r  r%   rp   r  )r  r  r  r  r  r  Z	copy_maskr  r  r  	normalize  s&    
zBaseImage.normalizec             C   s:   t j||d tdk r&t| j|}nt| j||}|S )a  Simulates an oil painting by replace each pixel with most frequent
        surrounding color.

        :param radius: The size of the surrounding neighbors.
        :type radius: :class:`numbers.Real`
        :param sigma: The standard deviation used by the Gaussian operator.
                      This is only available with ImageMagick-7.
        :type sigma: :class:`numbers.Real`

        .. versionadded:: 0.5.4
        )r  r  i   )r   rQ  r   r   ZMagickOilPaintImager  )r  r  r  r  r  r  r  	oil_paint  s
    zBaseImage.oil_paintc       	   
   C   s   t |trt|}t |tr$t|}tj||d tj|d tj|d | | |dkrxt| j	|j
|j
||}nb| |}tdk rt| j	||j
|j
||}n4t| j	|}t| j	|j
|j
||}t| j	| W dQ R X W dQ R X |S )a  Replace any color that matches ``target`` with ``fill``. Use
        ``fuzz`` to control the threshold of the target match.
        The ``invert`` will replace all colors *but* the  pixels matching
        the ``target`` color.

        :param target: The color to match.
        :type target: :class:`wand.color.Color`
        :param fill: The color to paint with.
        :type fill: :class:`wand.color.Color`
        :param fuzz: Normalized real number between `0.0` and
                     :attr:`quantum_range`. Default is `0.0`.
        :type fuzz: class:`numbers.Real`
        :param invert: Replace all colors that do not match target.
                       Default is ``False``.
        :type invert: :class:`bool`
        :param channel: Optional color channel to target. See
                        :const:`CHANNELS`
        :type channel: :class:`basestring`

        .. versionadded:: 0.5.4

        .. versionchanged:: 0.5.5
           Added ``channel`` paramater.
        )targetr  )r   )invertNi   )r  r   r   r   r  rQ  r,  r   ZMagickOpaquePaintImager  r2  r  r   ZMagickOpaquePaintImageChannelr  )	r  r  r  r   r  r  r  r  r  r  r  r  opaque_paint  s:    



"zBaseImage.opaque_paintc             C   s&   t | j}|r|| _|   t|S )a  Attempts to crop each frame to the smallest image without altering
        the animation. For best results, call
        :meth:`Image.coalesce() <wand.image.BaseImage.coalesce>` before
        manipulating any frames. For timing accuracy, any
        :attr:`SingleImage.delay <wand.sequence.SingleImage.delay>` overwrites
        must be applied after optimizing layers.

        .. note::

            This will only affect ``GIF`` image formates.

        .. versionadded:: 0.5.0
        )r   ZMagickOptimizeImageLayersr  r  r  )r  r  r  r  r  optimize_layers  s
    zBaseImage.optimize_layersc             C   s   t jrt | jS tddS )zIterates over frames, and sets transparent values for each
        pixel unchanged by previous frame.

        .. note::

            This will only affect ``GIF`` image formates.

        .. versionadded:: 0.5.0
        zY`MagickOptimizeImageTransparency' not available on current version of MagickWand library.N)r   ZMagickOptimizeImageTransparencyr  r  )r  r  r  r  optimize_transparency2  s    zBaseImage.optimize_transparencyr   c             C   s   t j|d t|}tdkrP|dkr4t| j|}q| |}t| j||}nL|dkrht	| j|}n4| |}t
| j|}t	| j|}t
| j| |S )a~  Executes a ordered-based dither operations based on predetermined
        threshold maps.

        +-----------+-------+-----------------------------+
        | Map       | Alias | Description                 |
        +===========+=======+=============================+
        | threshold | 1x1   | Threshold 1x1 (non-dither)  |
        +-----------+-------+-----------------------------+
        | checks    | 2x1   | Checkerboard 2x1 (dither)   |
        +-----------+-------+-----------------------------+
        | o2x2      | 2x2   | Ordered 2x2 (dispersed)     |
        +-----------+-------+-----------------------------+
        | o3x3      | 3x3   | Ordered 3x3 (dispersed)     |
        +-----------+-------+-----------------------------+
        | o4x4      | 4x4   | Ordered 4x4 (dispersed)     |
        +-----------+-------+-----------------------------+
        | o8x8      | 8x8   | Ordered 8x8 (dispersed)     |
        +-----------+-------+-----------------------------+
        | h4x4a     | 4x1   | Halftone 4x4 (angled)       |
        +-----------+-------+-----------------------------+
        | h6x6a     | 6x1   | Halftone 6x6 (angled)       |
        +-----------+-------+-----------------------------+
        | h8x8a     | 8x1   | Halftone 8x8 (angled)       |
        +-----------+-------+-----------------------------+
        | h4x4o     |       | Halftone 4x4 (orthogonal)   |
        +-----------+-------+-----------------------------+
        | h6x6o     |       | Halftone 6x6 (orthogonal)   |
        +-----------+-------+-----------------------------+
        | h8x8o     |       | Halftone 8x8 (orthogonal)   |
        +-----------+-------+-----------------------------+
        | h16x16o   |       | Halftone 16x16 (orthogonal) |
        +-----------+-------+-----------------------------+
        | c5x5b     | c5x5  | Circles 5x5 (black)         |
        +-----------+-------+-----------------------------+
        | c5x5w     |       | Circles 5x5 (white)         |
        +-----------+-------+-----------------------------+
        | c6x6b     | c6x6  | Circles 6x6 (black)         |
        +-----------+-------+-----------------------------+
        | c6x6w     |       | Circles 6x6 (white)         |
        +-----------+-------+-----------------------------+
        | c7x7b     | c7x7  | Circles 7x7 (black)         |
        +-----------+-------+-----------------------------+
        | c7x7w     |       | Circles 7x7 (white)         |
        +-----------+-------+-----------------------------+

        :param threshold_map: Name of threshold dither to use, followed by
                              optional arguments.
        :type threshold_map: :class:`basestring`
        :param channel: Optional argument to apply dither to specific color
                        channel. See :const:`CHANNELS`.
        :type channel: :class:`basestring`

        .. versionadded:: 0.5.7
        )threshold_mapi   N)r   rR  r	   r   r   ZMagickOrderedPosterizeImager  r  Z"MagickOrderedPosterizeImageChannelZMagickOrderedDitherImager  )r  r  r  Zbmapr  r  r  r  r  r  ordered_ditherE  s"    9

zBaseImage.ordered_ditherc          	   C   s   t j|d td}td}t| j}t| j}tt	|t
|t
|t
|t
|}t|svtd|j|j|j|jfS )aB  Helper method to translate geometry format, and calculate
        meta-characters against image dimensions.

        See "Image Geometry" definitions & examples for more info:
        https://imagemagick.org/script/command-line-processing.php#geometry

        :param geometry: user string following ImageMagick's geometry format.
        :type geometry: :class:`basestring`
        :returns: Calculated width, height, offset-x, & offset-y.
        :rtype: :class:`tuple`
        :raises ValueError: If given geometry can not be parsed.

        .. versionadded:: 0.5.6
        )r  r   zUnable to parse geometry)r   rR  r  rs  rh  r  r  r   ParseMetaGeometryr	   r  r  r  r4  )r  r  r  r  r  r  r  r  r  r  parse_meta_geometry  s    


zBaseImage.parse_meta_geometryc             C   sH   | j | j d}x | D ]\}}|||}qW || jd< t| dS )a(  Convenience method that expands ImageMagick's `Percent Escape`_
        characters into image attribute values.

        .. _Percent Escape: https://imagemagick.org/script/escape.php

        .. code::

            with wand.image import Image

            with Image(filename='tests/assets/sasha.jpg') as img:
                print(img.percent_escape('%f %wx%h'))
                #=> sasha.jpg 204x247

        .. note::

            Not all percent escaped values can be populated as I/O operations
            are managed by Python, and not the CLI utility.

        :param string_format: The precent escaped string to be translated.
        :type string_format: :class:`basestring`
        :returns: String of expanded values.
        :rtype: :class:`basestring`

        .. versionadded:: 0.5.6
        )z%mz	%[magick]r  INFO)r  itemsr   r  r   	make_blob)r  Zstring_formatZlocal_overwritesre  vr  r  r  percent_escape  s    

zBaseImage.percent_escapec          	   C   sV  t j|d t jtd|d t }|rt j|d t|}t| j	d| t
|tr|jrpt|t|j |jrt||j |jr|j t||jj W dQ R X t||j |jr|j t||jj W dQ R X |jrt||j n|rtdt| tdk r*t| j	||}nt|}t| j	||||}t|}|S )	a/  Creates a special effect simulating a Polaroid photo.

        :see: Example of :ref:`polaroid`.

        :param angle: applies a shadow effect along this angle.
        :type angle: :class:`numbers.Real`
        :param caption: Writes a message at the bottom of the photo's border.
        :type caption: :class:`basestring`
        :param font: Specify font style.
        :type font: :class:`wand.font.Font`
        :param method: Interpolation method. ImageMagick-7 only.
        :type method: :class:`basestring`

        .. versionadded:: 0.5.4
        )r  z$wand.image.PIXEL_INTERPOLATE_METHODS)rc  )r}  s   CaptionNz0font must be in instance of wand.font.Font, not i   )r   rQ  r#  r6   r   ZNewDrawingWandrR  r	   MagickSetImagePropertyr  r  r   rF  ZDrawSetFontr  ZDrawSetFontSizer  ZDrawSetFillColorr2  ZDrawSetTextAntialiasr+  rG  ZDrawSetStrokeColorrH  ZDrawSetStrokeWidthr  r  r   ZMagickPolaroidImagerp   ZDestroyDrawingWand)r  r  r}  rL  rc  Zctx_ptrr  ra  r  r  r  polaroid  sF    




zBaseImage.polaroidc             C   s\   t jdkrd}t|t|tjs2tdt| t|}t	j
| | }t | j|d? |S )aB  Replace image with the sum of all images in a sequence by
        calculating the pixel values a coefficient-weight value, and a
        polynomial-exponent.

        For example::

            with Image(filename='rose:') as img:
                img.polynomial(arguments=[0.5, 1.0])

        The output image will be calculated as:

        .. math::

            output = 0.5 * image ^ {1.0}

        This can work on multiple images in a sequence by calculating across
        each frame in the image stack.

        .. code::

            with Image(filename='2frames.gif') as img:
                img.polynomial(arguments=[0.5, 1.0, 0.25, 1.25])

        Where the results would be calculated as:

        .. math::

            output = 0.5 * frame1 ^ {1.0} + 0.25 * frame2 ^ {1.25}

        .. warning::

            This class method is only available with ImageMagick 7.0.8-41, or
            greater.

        :param arguments: A list of real numbers where at least two numbers
                         (weight & exponent) are need for each image in the
                         sequence.
        :type arguments: :class:`collections.abc.Sequence`
        :raises WandLibraryVersionError: If system's version of ImageMagick
                                         does not support this method.

        .. versionadded:: 0.5.5
        Nz8Method requires ImageMagick version 7.0.8-41 or greater.z"expected sequence of doubles, not r   )r   ZMagickPolynomialImager   r  r   r8  r  r  r  r  r  r  )r  r  r  r;  r<  r  r  r  r  
  s    .
zBaseImage.polynomialr   c             C   s6   t j|d t jtd|d t|}t| j||S )a6  Reduce color levels per channel.

        :param levels: Number of levels per channel.
        :type levels: :class:`numbers.Integral`
        :param dither: Dither method to apply.
                       See :const:`DITHER_METHODS`.
        :type dither: `basestring`

        .. versionadded:: 0.5.0
        )levelszwand.image.DITHER_METHODS)r  )r   rA  r#  r)   rp   r   ZMagickPosterizeImager  )r  r  r  Z
dither_idxr  r  r  	posterizeB  s
    
zBaseImage.posterizec             C   s   t j|d |dkr| j}t jtd|d t j|d tdk rLt j|d n4|dkrZd	}n|d
krfd}t jtd|d t|}t j|d t	
| j|t||||S )av  `quantize` analyzes the colors within a sequence of images and
        chooses a fixed number of colors to represent the image. The goal of
        the algorithm is to minimize the color difference between the input and
        output image while minimizing the processing time.

        :param number_colors: The target number of colors to reduce the image.
        :type number_colors: :class:`numbers.Integral`
        :param colorspace_type: Available value can be found
                                in the :const:`COLORSPACE_TYPES`. Defaults
                                :attr:`colorspace`.
        :type colorspace_type: :class:`basestring`
        :param treedepth: A value between ``0`` & ``8`` where ``0`` will
                         allow ImageMagick to calculate the optimal depth
                         with ``Log4(number_colors)``. Default value is ``0``.
        :type treedepth: :class:`numbers.Integral`
        :param dither: Perform dither operation between neighboring pixel
                       values. If using ImageMagick-6, this can be a value
                       of ``True``, or ``False``. With ImageMagick-7, use
                       a string from :const:`DITHER_METHODS`. Default
                       ``False``.
        :type dither: :class:`bool`, or :class:`basestring`
        :param measure_error: Include total quantization error of all pixels
                              in an image & quantized value.
        :type measure_error: :class:`bool`

        .. versionadded:: 0.4.2

        .. versionchanged:: 0.5.9
           Fixed ImageMagick-7 ``dither`` argument, and added keyword defaults.
        )r  Nzwand.image.COLORSPACE_TYPES)r<  )	treedepthi   )r  Fr   Tr  zwand.image.DITHER_METHODS)measure_error)r   rA  r  r#  r#   r   r,  r)   rp   r   ZMagickQuantizeImager  )r  r  r<  r  r  r  r  r  r  quantizeU  s,    "
zBaseImage.quantizec             C   s   t j||d d|  k r"dkr0n n
|| j9 }d|  k rDdkrRn n
|| j9 }|dkrlt| j||}nR| |}tdk rt| j|||}n,t	| j|}t| j||}t	| j| |S )a  Performs a random dither to force a pixel into a binary black &
        white state. Each color channel operarates independently from each
        other.

        :param low: bottom threshold. Any pixel value below the given value
                    will be rendered "0", or no value. Given threshold value
                    can be between ``0.0`` & ``1.0``, or ``0`` &
                    :attr:`quantum_range`.
        :type low: :class:`numbers.Real`
        :param high: top threshold. Any pixel value above the given value
                     will be rendered as max quantum value. Given threshold
                     value can be between ``0.0`` & ``1.0``, or ``0`` &
                     :attr:`quantum_range`.
        :type high: :class:`numbers.Real`
        :param channel: Optional argument to apply dither to specific color
                        channel. See :const:`CHANNELS`.
        :type channel: :class:`basestring`

        .. versionadded:: 0.5.7
        )lowhighr   g      ?Ni   )
r   rQ  r  r   ZMagickRandomThresholdImager  r  r   Z!MagickRandomThresholdImageChannelr  )r  r  r  r  r  rb  r  r  r  r  random_threshold  s$    


zBaseImage.random_thresholdc             C   s   |  |}td}td}tdk rFt| j|t|t| n8t| j|}t	| jt|t| t| j| |j
|j
fS )a  Calculate the minimum and maximum of quantum values in image.

        .. code:: python

            from wand.image import Image

            with Image(filename='input.jpg') as img:
                minima, maxima = img.range_channel()

        :param channel: Select which color channel to evaluate. See
                        :const:`CHANNELS`. Default ``'default_channels'``.
        :type channel: :class:`basestring`
        :returns: Tuple of :attr:`minima` & :attr:`maxima`
                  values. Each value will be between 0.0 &
                  :attr:`quantum_range`.
        :rtype: :class:`tuple`

        .. versionadded:: 0.5.3
        g        i   )r  r  r  r   r   ZMagickGetImageChannelRanger  r  r  ZMagickGetImageRanger4  )r  r  rb  Z	min_colorZ	max_colorr  r  r  r  rm    s    



zBaseImage.range_channelc             C   s   t jdkrd}t||dkr"|}|dkr.|}|dkr:|}tj||||d d|  k r`dkrnn n
|| j9 }d|  k rdkrn n
|| j9 }d|  k rdkrn n
|| j9 }d|  k rdkrn n
|| j9 }t | j||||S )a}  Applies soft & hard thresholding.

        For a soft thresholding, parameters should be monotonically increasing:

            with Image(filename='text.png') as img:
                img.range_threshold(0.2, 0.4, 0.6, 0.8)

        For a hard thresholding, parameters should be the same:

            with Image(filename='text.png') as img:
                img.range_threshold(0.4, 0.4, 0.6, 0.6)

        .. warning::

            This class method is only available with ImageMagick 7.0.8-41, or
            greater.

        :param low_black: Define the minimum threshold value.
        :type low_black: :class:`numbers.Real`
        :param low_white: Define the minimum threshold value.
        :type low_white: :class:`numbers.Real`
        :param high_white: Define the maximum threshold value.
        :type high_white: :class:`numbers.Real`
        :param high_black: Define the maximum threshold value.
        :type high_black: :class:`numbers.Real`
        :raises WandLibraryVersionError: If system's version of ImageMagick
                                         does not support this method.

        .. versionadded:: 0.5.5
        Nz8Method requires ImageMagick version 7.0.8-41 or greater.)	low_black	low_white
high_white
high_blackr   g      ?)r   ZMagickRangeThresholdImager   r   rQ  r  r  )r  r  r  r  r  r  r  r  r  range_threshold  s,    "





zBaseImage.range_thresholdc             C   sV   d}d}t jdkrtdn6|dkr6t | j|d}nt|trRt | j||j}|S )a  Sets the read mask where the gray values of the clip mask
        are used to blend during composite operations. Call this method with
        a ``None`` argument to clear any previously set masks.

        This method is also useful for :meth:`compare` method for limiting
        region of interest.

        .. warning::
           This method is only available with ImageMagick-7.

        :param clip_mask: Image to reference as blend mask.
        :type clip_mask: :class:`BaseImage`

        .. versionadded:: 0.5.7
        Fr   NzMethod requires ImageMagick-7.)r   MagickSetImageMaskr   r  r  r=   )r  	clip_maskr  ZReadPixelMaskr  r  r  	read_mask  s    



zBaseImage.read_maskc             C   sF   t |tstdt| tjtd|d t|}t	| j
|j
|S )a  Rebuild image palette with closest color from given affinity image.

        :see: Example of :ref:`remap`.

        :param affinity: reference image.
        :type affinity: :class:`BaseImage`
        :param method: dither method. See :const:`DITHER_METHODS`.
                       Default is ``'no'`` dither.
        :type method: :class:`basestring`

        .. versionadded:: 0.5.3
        z*Expecting affinity to be a BaseImage, not zwand.image.DITHER_METHODS)rc  )r  r=   r  r  r   r#  r)   rp   r   ZMagickRemapImager  )r  Zaffinityrc  ra  r  r  r  remap;  s    

zBaseImage.remapc       	      C   s  |dkr| j \}}|dkr$| j \}}tj|||d |dk rNtdt| n:|dk rhtdt| n t|ttjfst	dt| t|tryt
|}W n, tk
r   tt|d tt
 Y nX n:t|tjr
d|  krtt
k s
n tt|d	 tt|}| jrt| j| _|   t| j t| j}t| j xNt|d D ](}t| j| t| j||||}qhW nt| j||||}|S )
a  Adjust the number of pixels in an image so that when displayed at
        the given Resolution or Density the image will still look the same size
        in real world terms.

        .. note::

            This method will automatically :meth:`coalesce` & resample all
            frames in a GIF animation. For other image formats,
            :meth:`resample` will only effect the current image in the stack.
            Use :meth:`iterator_reset` & :meth:`iterator_next` to traverse
            the image stack to resample all images in a multi-layer document.

            .. code::

                with Image(filename='input.tiff') as img:
                    img.iterator_reset()
                    while True:
                        img.resample(128, 128)
                        if not img.iterator_next():
                            break

        :param x_res: the X resolution (density) in the scaled image. default
                      is  the original resolution.
        :type x_res: :class:`numbers.Real`
        :param y_res: the Y resolution (density) in the scaled image. default
                      is the original resolution.
        :type y_res: :class:`numbers.Real`
        :param filter: a filter type to use for resizing. choose one in
                       :const:`FILTER_TYPES`. default is ``'undefined'``
                       which means IM will try to guess best one to use.
        :type filter: :class:`basestring`, :class:`numbers.Integral`
        :param blur: the blur factor where > 1 is blurry, < 1 is sharp.
                     default is 1
        :type blur: :class:`numbers.Real`

        .. versionadded:: 0.4.5
        N)x_resy_resr   r   z!x_res must be a Real number, not z!y_res must be a Real number, not zPfilter must be one string defined in wand.image.FILTER_TYPES or an integer, not z) is an invalid filter type; choose on in r   z is an invalid filter type)r  r   rQ  r  r  r  r   r  r  r  r+   rp   r  r  r  r  r  r*  r   r  r  r  r$  r%  r&  r   r'  ZMagickResampleImage)	r  r  r  filterr   rf  r(  r)  r  r  r  r  resampleR  sJ    (


zBaseImage.resamplec             C   s   t | jd dS )zReset the coordinate frame of the image so to the upper-left corner
        is (0, 0) again (crop and rotate operations change it).

        .. versionadded:: 0.2.0

        N)r   MagickResetImagePager  )r  r  r  r  r1    s    zBaseImage.reset_coordsc             C   s   dS )z{Abstract method prototype.
        See :meth:`wand.image.Image.reset_sequence()`.

        .. versionadded:: 0.6.0
        Nr  )r  r  r  r  r    s    zBaseImage.reset_sequencec             C   s  |dkr| j }|dkr| j}tj||d tj|d t|ttjfsVt	dt
| t|tryt|}W q tk
r   tt
|d t
t Y qX n6t|tjrd|  krttk sn tt
|d tt|}| jrpt| j| _|   t| j t| j}t| j x8t|d D ](}t| j| t| j||||}q2W t| j|| n$t| j||||}t| j|| |S )	aV  Resizes the image.

        :param width: the width in the scaled image. default is the original
                      width
        :type width: :class:`numbers.Integral`
        :param height: the height in the scaled image. default is the original
                       height
        :type height: :class:`numbers.Integral`
        :param filter: a filter type to use for resizing. choose one in
                       :const:`FILTER_TYPES`. default is ``'undefined'``
                       which means IM will try to guess best one to use
        :type filter: :class:`basestring`, :class:`numbers.Integral`
        :param blur: the blur factor where > 1 is blurry, < 1 is sharp.
                     default is 1
        :type blur: :class:`numbers.Real`

        .. versionchanged:: 0.2.1
           The default value of ``filter`` has changed from ``'triangle'``
           to ``'undefined'`` instead.

        .. versionchanged:: 0.1.8
           The ``blur`` parameter changed to take :class:`numbers.Real`
           instead of :class:`numbers.Rational`.

        .. versionadded:: 0.1.1

        N)r  r  )r   zPfilter must be one string defined in wand.image.FILTER_TYPES or an integer, not z) is an invalid filter type; choose on in r   z is an invalid filter typer   )r  r  r   r0  rQ  r  r   r  r  r  r  r+   rp   r  r  r  r  r  r  r*  r   r  r  r  r$  r%  r&  r   r'  ZMagickResizeImager\  )r  r  r  r  r   r(  r)  r  r  r  r  r    sD    
zBaseImage.resizec          	   C   s   |dkrt d}nt|tr$t |}tj|d tj|d | | jrt| j	| _	| 
  t| j	 t| j	}t| j	 xhtd|d D ]6}t| j	| t| j	|j|}|rt| j	d qW nt| j	|j|}|r|   W dQ R X |S )a  Rotates the image right.  It takes a ``background`` color
        for ``degree`` that isn't a multiple of 90.

        :see: Example of :ref:`rotate`.

        :param degree: a degree to rotate. multiples of 360 affect nothing
        :type degree: :class:`numbers.Real`
        :param background: an optional background color.
                           default is transparent
        :type background: :class:`wand.color.Color`
        :param reset_coords: optional flag. If set, after the rotation, the
            coordinate frame will be relocated to the upper-left corner of
            the new image. By default is `True`.
        :type reset_coords: :class:`bool`

        .. versionadded:: 0.2.0
           The ``reset_coords`` parameter.

        .. versionadded:: 0.1.8

        NrU   )rM   )r  r   r   )r   r  r   r   r  rQ  r*  r   r  r  r  r$  r%  r&  r   r'  ZMagickRotateImager2  r  r1  )r  r  rM   r1  r(  r)  r  r  r  r  r    s4    

zBaseImage.rotatec             C   s   t jsd}t|tj|d |rr| |}tdk rFt | j||}qt 	| j|}t | j|}t 	| j| nt | j|}|S )a  Blur an image in a radius around the center of an image.

        .. warning:: Requires ImageMagick-6.8.8 or greater.

        :see: Example of :ref:`rotational_blur`.

        :param angle: Degrees of rotation to blur with.
        :type angle: :class:`numbers.Real`
        :param channel: Optional channel to apply the effect against. See
                        :const:`CHANNELS` for a list of possible values.
        :type channel: :class:`basestring`
        :raises WandLibraryVersionError: If system's version of ImageMagick
                                         does not support this method.

        .. versionadded:: 0.5.4
        zTMethod `rotational_blur` not available on installed version of ImageMagick library. )r  i   )
r   ZMagickRotationalBlurImager   r   rQ  r  r   Z MagickRotationalBlurImageChannelr  r  )r  r  r  r  r  r  r  r  r  r  rotational_blur(  s     
zBaseImage.rotational_blurc             C   s   |dkr| j }|dkr| j}tj||d | jrt| j| _|   t	| j t
| j}t| j x2t|d D ]"}t| j| t| j||}qxW t| j|| n t| j||}t| j|| t|S )a  Resizes the image by sampling the pixels.  It's basically quicker
        than :meth:`resize()` except less quality as a trade-off.

        :param width: the width in the scaled image. default is the original
                      width
        :type width: :class:`numbers.Integral`
        :param height: the height in the scaled image. default is the original
                       height
        :type height: :class:`numbers.Integral`

        .. versionadded:: 0.3.4

        N)r  r  r   )r  r  r   r0  r*  r   r  r  r  r$  r%  r&  r   r'  ZMagickSampleImager\  r  )r  r  r  r(  r)  r  r  r  r  sampleO  s$    zBaseImage.samplec             C   s   t j||d t| j||S )a  Increase image size by scaling each pixel value by given ``columns``
        and ``rows``.

        :param columns: The number of columns, in pixels, to scale the image
                        horizontally.
        :type columns: :class:`numbers.Integral`
        :param rows: The number of rows, in pixels, to scale the image
                        vertically.
        :type rows: :class:`numbers.Integral`

        .. versionadded:: 0.5.7
        )r  r  )r   r0  r   ZMagickScaleImager  )r  r  r  r  r  r  scales  s    zBaseImage.scalec             C   s   t j|||d |dkr,t| j|||}nV| |}tdk rTt| j||||}n.t| j|}t| j|||}t| j| |S )a_  Blur an image within a given threshold.

        For best effects, use a value between 10% and 50% of
        :attr:`quantum_range`

        .. code::

            from wand.image import Image

            with Image(filename='photo.jpg') as img:
                # Apply 8x3 blur with a 10% threshold
                img.selective_blur(8.0, 3.0, 0.1 * img.quantum_range)

        :see: Example of :ref:`selective_blur`.

        :param radius: Size of gaussian aperture.
        :type radius: :class:`numbers.Real`
        :param sigma: Standard deviation of gaussian operator.
        :type sigma: :class:`numbers.Real`
        :param threshold: Only pixels within contrast threshold are effected.
                          Value should be between ``0.0`` and
                          :attr:`quantum_range`.
        :type threshold: :class:`numbers.Real`
        :param channel: Optional color channel to target. See
                        :const:`CHANNELS`
        :type channel: :class:`basestring`

        .. versionadded:: 0.5.3

        .. versionchanged:: 0.5.5
           Added ``channel`` argument.
        )r  r  r   Ni   )	r   rQ  r   ZMagickSelectiveBlurImager  r  r   ZMagickSelectiveBlurImageChannelr  )r  r  r  r   r  r  r  r  r  r  r  selective_blur  s(    $
zBaseImage.selective_blur皙?c             C   s<   t j|d d|  k r dkr.n n
|| j9 }t| j|S )a  Creates a Sepia Tone special effect similar to a darkroom chemical
        toning.

        :see: Example of :ref:`sepia_tone`.

        :param threshold: The extent of the toning. Value can be between ``0``
                          & :attr:`quantum_range`, or ``0`` & ``1.0``.
                          Default value is ``0.8`` or "80%".
        :type threshold: :class:`numbers.Real`

        .. versionadded:: 0.5.7
        )r   g        g      ?)r   rQ  r  r   ZMagickSepiaToneImager  )r  r   r  r  r  
sepia_tone  s    
zBaseImage.sepia_tonec             C   s    t j||d t| j|||S )a  Creates a 3D effect by simulating a light from an
        elevated angle.

        :see: Example of :ref:`shade`.

        :param gray: Isolate the effect on pixel intensity.
                     Default is False.
        :type gray: :class:`bool`
        :param azimuth: Angle from x-axis.
        :type azimuth: :class:`numbers.Real`
        :param elevation: Amount of pixels from the z-axis.
        :type elevation: :class:`numbers.Real`

        .. versionadded:: 0.5.0
        )azimuth	elevation)r   rQ  r   ZMagickShadeImager  )r  rg   r  r  r  r  r  shade  s    
zBaseImage.shadec             C   s0   t j||d t j||d t| j||||S )a  Generates an image shadow.

        :param alpha: Ratio of transparency.
        :type alpha: :class:`numbers.Real`
        :param sigma: Standard deviation of the gaussian filter.
        :type sigma: :class:`numbers.Real`
        :param x: x-offset.
        :type x: :class:`numbers.Integral`
        :param y: y-offset.
        :type y: :class:`numbers.Integral`

        .. versionadded:: 0.5.0
        )rm   r  )r  r  )r   rQ  rA  r   ZMagickShadowImager  )r  rm   r  r  r  r  r  r  shadow  s    zBaseImage.shadowc             C   s~   t j||d |dkr(t| j||}nR| |}tdk rNt| j|||}n,t| j|}t| j||}t| j| |S )a  Applies a gaussian effect to enhance the sharpness of an
        image.

        .. note::

            For best results, ensure ``radius`` is larger than
            ``sigma``.

            Defaults values of zero will have ImageMagick attempt
            to auto-select suitable values.

        :see: Example of :ref:`sharpen`.

        :param radius: size of gaussian aperture.
        :type radius: :class:`numbers.Real`
        :param sigma: Standard deviation of the gaussian filter.
        :type sigma: :class:`numbers.Real`
        :param channel: Optional color channel to target. See
                        :const:`CHANNELS`.
        :type channel: :class:`basestring`

        .. versionadded:: 0.5.0

        .. versionchanged:: 0.5.5
           Added ``channel`` argument.
        )r  r  Ni   )	r   rQ  r   ZMagickSharpenImager  r  r   ZMagickSharpenImageChannelr  )r  r  r  r  r  r  r  r  r  r  r    s    

zBaseImage.sharpenc             C   s   t j||d t| j||S )a0  Remove pixels from the edges.

        :param columns: amount to shave off both sides of the x-axis.
        :type columns: :class:`numbers.Integral`
        :param rows: amount to shave off both sides of the y-axis.
        :type rows: :class:`numbers.Integral`

        .. versionadded:: 0.5.0
        )r  r  )r   rA  r   ZMagickShaveImager  )r  r  r  r  r  r  shave*  s    zBaseImage.shaveWHITEc          	   C   sT   t |trt|}tj|d tj||d | t| j|j	||}W dQ R X |S )a  Shears the image to create a parallelogram, and fill the space
        created with a ``background`` color.

        :param background: Color to fill the void created by shearing the
                           image.
        :type background: :class:`wand.color.Color`
        :param x: Slide the image along the X-axis.
        :type x: :class:`numbers.Real`
        :param y: Slide the image along the Y-axis.
        :type y: :class:`numbers.Real`

        .. versionadded:: 0.5.4
        )rM   )r  r  N)
r  r   r   r   r  rQ  r   ZMagickShearImager  r2  )r  rM   r  r  r  r  r  r  shear9  s    
zBaseImage.shearc             C   s   t j|d t j||d |dkr6t| j|||}nV| |}tdk r^t| j||||}n.t	| j|}t| j|||}t	| j| |S )ai  Modifies the contrast of the image by applying non-linear sigmoidal
        algorithm.

        .. code:: python

            with Image(filename='photo.jpg') as img:
                img.sigmoidal_contrast(sharpen=True,
                                       strength=3,
                                       midpoint=0.65 * img.quantum_range)

        :param sharpen: Increase the contrast when ``True`` (default), else
                        reduces contrast.
        :type sharpen: :class:`bool`
        :param strength: How much to adjust the contrast. Where a value of
                         ``0.0`` has no effect, ``3.0`` is typical, and
                         ``20.0`` is extreme.
        :type strength: :class:`numbers.Real`
        :param midpoint: Normalized value between `0.0` & :attr:`quantum_range`
        :type midpoint: :class:`numbers.Real`
        :param channel: Optional color channel to target. See
                        :const:`CHANNELS`.
        :type channel: :class:`basestring`

        .. versionadded:: 0.5.4

        .. versionchanged:: 0.5.5
           Added ``channel`` argument.
        )r  )r  midpointNi   )
r   r,  rQ  r   ZMagickSigmoidalContrastImager  r  r   Z#MagickSigmoidalContrastImageChannelr  )r  r  r  r  r  r  r  r  r  r  r  sigmoidal_contrastQ  s$     
zBaseImage.sigmoidal_contrastc       
   
   C   s   t j|d t|ts&tdt| tdddd}td}t	dk rt
t|}t| jd| t| j|jt|t|}n>t jtd|d t|}t| j|j||t|t|}|s|   n
t|}t|j|j|j|jd	}	|	|jfS )
a	  Scan image for best matching ``reference`` image, and
        return location & similarity.

        Use parameter ``threshold`` to stop subimage scanning if the matching
        similarity value is below the given value. This is the same as the CLI
        ``-similarity-threshold`` option.

        This method will always return a location & the lowest computed
        similarity value. Users are responsible for checking the similarity
        value to determine if a matching location is valid. Traditionally, a
        similarity value greater than `0.3183099` is considered dissimilar.

        .. code:: python

            from wand.image import Image

            dissimilarity_threshold = 0.318
            similarity_threshold = 0.05
            with Image(filename='subject.jpg') as img:
                with Image(filename='object.jpg') as reference:
                    location, diff = img.similarity(reference,
                                                    similarity_threshold)
                    if diff > dissimilarity_threshold:
                        print('Images too dissimilar to match')
                    elif diff <= similarity_threshold:
                        print('First match @ {left}x{top}'.format(**location))
                    else:
                        print('Best match @ {left}x{top}'.format(**location))

        .. warning::

            This operation can be slow to complete.

        :param reference: Image to search for.
        :type reference: :class:`wand.image.Image`
        :param threshold: Stop scanning if reference similarity is
                          below given threshold. Value can be between ``0.0``
                          and :attr:`quantum_range`. Default is ``0.0``.
        :type threshold: :class:`numbers.Real`
        :param metric: specify which comparison algorithm to use. See
                       :const:`COMPARE_METRICS` for a list of values.
                       Only used by ImageMagick-7.
        :type metric: :class:`basestring`
        :returns: List of location & similarity value. Location being a
                  dictionary of ``width``, ``height``, ``left``, & ``top``.
                  The similarity value is the compare distance, so a value of
                  ``0.0`` means an exact match.
        :rtype: :class:`tuple` (:class:`dict`, :class:`numbers.Real`)

        .. versionadded:: 0.5.4

           has been added.
        )r   z7reference must be in instance of wand.image.Image, not r   g        i   s   compare:similarity-thresholdzwand.image.COMPARE_METRICS)r  )r  r  r  r  )r   rQ  r  r=   r  r  r   r  r  r   r	   r  r   r  r  ZMagickSimilarityImager  r#  r$   rp   r  DestroyMagickWandr  r  r  r  r  r4  )
r  	referencer   r  ZriodiffZartifact_valuer  rg  locationr  r  r  
similarity  s>    7





zBaseImage.similarityc             C   s"   t j|||d t| j|||S )a  Simulates a pencil sketch effect. For best results, ``radius``
        value should be larger than ``sigma``.

        :see: Example of :ref:`sketch`.

        :param radius: size of Gaussian aperture.
        :type radius: :class:`numbers.Real`
        :param sigma: standard deviation of the Gaussian operator.
        :type sigma: :class:`numbers.Real`
        :param angle: direction of blur.
        :type angle: :class:`numbers.Real`

        .. versionadded:: 0.5.3
        )r  r  r  )r   rQ  r   ZMagickSketchImager  )r  r  r  r  r  r  r  sketch  s    zBaseImage.sketchc             C   sF   t j|d t| j t| jt||}|r>|| _|   t|S )a  Appends all images together. Similar behavior to :meth:`concat`,
        but with an optional offset between images.

        :param stacked: If True, will join top-to-bottom. If False, join images
                        from left-to-right (default).
        :type stacked: :class:`bool`
        :param offset: Minimum space (in pixels) between each join.
        :type offset: :class:`numbers.Integral`

        .. versionadded:: 0.5.3
        )r  )r   rA  r   r&  r  ZMagickSmushImagesr  r  )r  r  r  r  r  r  r  smush  s    zBaseImage.smushc             C   sv   t j|d |dkr$t| j|}nN| |}tdk rHt| j||}n*t| j|}t| j|}t| j| |S )a  Simulates extreme overexposure.

        :see: Example of :ref:`solarize`.

        :param threshold: between ``0.0`` and :attr:`quantum_range`.
        :type threshold: :class:`numbers.Real`
        :param channel: Optional color channel to target. See
                        :const:`CHANNELS`
        :type channel: :class:`basestring`

        .. versionadded:: 0.5.3

        .. versionchanged:: 0.5.5
           Added ``channel`` argument.
        )r   Ni   )	r   rQ  r   ZMagickSolarizeImager  r  r   ZMagickSolarizeImageChannelr  )r  r   r  r  r  r  r  r  r  solarize	  s    
zBaseImage.solarizerd   c          
   C   sb  t jtd|d t|tjs,tdt| t j|d t| }t	 }x|
 D ]\}}t|trjt|}|\}}	|| ||	 |f}
|td @ r||
j |td @ r||
j |td @ r||
j |td @ r||
j W d	Q R X qPW t|}tj| | }td
k r0t| j||||}n.t| j|}t| j|||}t| j| |S )a  Interpolates color values between points on an image.

        The ``colors`` argument should be a dict mapping
        :class:`~wand.color.Color` keys to coordinate tuples.

        For example::

            from wand.color import Color
            from wand.image import Image

            colors = {
                Color('RED'): (10, 50),
                Color('YELLOW'): (174, 32),
                Color('ORANGE'): (74, 123)
            }
            with Image(filename='input.png') as img:
                img.sparse_color('bilinear', colors)

        The available interpolate methods are:

        - ``'barycentric'``
        - ``'bilinear'``
        - ``'shepards'``
        - ``'voronoi'``
        - ``'inverse'``
        - ``'manhattan'``

        You can control which color channels are effected by building a custom
        channel mask. For example::

            from wand.image import Image, CHANNELS

            with Image(filename='input.png') as img:
                colors = {
                    img[50, 50]: (50, 50),
                    img[100, 50]: (100, 50),
                    img[50, 75]: (50, 75),
                    img[100, 100]: (100, 100)
                }
                # Only apply Voronoi to Red & Alpha channels
                mask = CHANNELS['red'] | CHANNELS['alpha']
                img.sparse_color('voronoi', colors, channel_mask=mask)

        :param method: Interpolate method. See :const:`SPARSE_COLOR_METHODS`
        :type method: :class:`basestring`
        :param colors: A dictionary of :class:`~wand.color.Color` keys mapped
                       to an (x, y) coordinate tuple.
        :type colors: :class:`abc.Mapping`
                      { :class:`~wand.color.Color`: (int, int) }
        :param channel_mask: Isolate specific color channels to apply
                             interpolation. Default to RGB channels.
        :type channel_mask: :class:`numbers.Integral`

        .. versionadded:: 0.5.3
        zwand.image.SPARSE_COLOR_METHODS)rc  zColors must be a dict, not)r  rf   ri   rk   rm   Ni   )r   r#  r8   r  r   Mappingr  r  r[  r  r  r   r   r  r"   rf   ri   rk   rm   r  r  r  r   r   ZMagickSparseColorImager  r  )r  rc  r;  r  ra  r  r  r  r  r  cr;  r  r  r  r  r  sparse_color*  sN    :



zBaseImage.sparse_colorc             C   s&   t j||||d t| j||||S )aK  Partitions image by splicing a ``width`` x ``height`` rectangle at
        (``x``, ``y``) offset coordinate. The space inserted will be replaced
        by the :attr:`background_color` value.

        :param width: number of pixel columns.
        :type width: :class:`numbers.Integral`
        :param height: number of pixel rows.
        :type height: :class:`numbers.Integral`
        :param x: offset on the X-axis.
        :type x: :class:`numbers.Integral`
        :param y: offset on the Y-axis.
        :type y: :class:`numbers.Integral`

        .. versionadded:: 0.5.3
        )r  r  r  r  )r   rA  r   ZMagickSpliceImager  )r  r  r  r  r  r  r  r  splice  s    zBaseImage.splicec             C   sR   t j|d t jtd|d t|}tdk r>t| j|}nt| j||}|S )aU  Randomly displace pixels within a defined radius.

        :see: Example of :ref:`spread`.

        :param radius: Distance a pixel can be displaced from source. Default
                       value is ``0.0``, which will allow ImageMagick to auto
                       select a radius.
        :type radius: :class:`numbers.Real`
        :param method: Interpolation method. Only available with ImageMagick-7.
                       See :const:`PIXEL_INTERPOLATE_METHODS`.

        .. versionadded:: 0.5.3

        .. versionchanged:: 0.5.7
           Added default value to ``radius``.
        )r  z$wand.image.PIXEL_INTERPOLATE_METHODS)rc  i   )	r   rQ  r#  r6   rp   r   r   ZMagickSpreadImager  )r  r  rc  ra  r  r  r  r  spread  s    
zBaseImage.spreadc       	      C   s   t jtd|d t j||d t|}|dkrDt| j|||}nV| |}t	dk rlt
| j||||}n.t| j|}t| j|||}t| j| |S )aj  Replace each pixel with the statistic results from neighboring pixel
        values. The ``width`` & ``height`` defines the size, or aperture, of
        the neighboring pixels.

        :see: Example of :ref:`statistic`.

        :param stat: The type of statistic to calculate. See
                     :const:`STATISTIC_TYPES`.
        :type stat: :class:`basestring`
        :param width: The size of neighboring pixels on the X-axis.
        :type width: :class:`numbers.Integral`
        :param height: The size of neighboring pixels on the Y-axis.
        :type height: :class:`numbers.Integral`
        :param channel: Optional color channel to target. See
                        :const:`CHANNELS`
        :type channel: :class:`basestring`

        .. versionadded:: 0.5.3

        .. versionchanged:: 0.5.5
           Added optional ``channel`` argument.
        zwand.image.STATISTIC_TYPES)r  )r  r  Ni   )r   r#  r9   rA  rp   r   ZMagickStatisticImager  r  r   ZMagickStatisticImageChannelr  )	r  statr  r  r  Zstat_idxr  r  r  r  r  r  r    s*    




zBaseImage.statisticc             C   sR   t |tstdt| tj|d t| j|j|}|rJ|| _| 	  t
|S )a{  Hide a digital watermark of an image within the image.

        .. code-block:: python

            from wand.image import Image

            # Embed watermark
            with Image(filename='source.png') as img:
                with Image(filename='gray_watermark.png') as watermark:
                    print('watermark size (for recovery)', watermark.size)
                    img.stegano(watermark)
                img.save(filename='public.png')

            # Recover watermark
            with Image(width=w, height=h, pseudo='stegano:public.png') as img:
                img.save(filename='recovered_watermark.png')

        :param watermark: Image to hide within image.
        :type watermark: :class:`wand.image.Image`
        :param offset: Start embedding image after a number of pixels.
        :type offset: :class:`numbers.Integral`

        .. versionadded:: 0.5.4
        z=Watermark image must be in instance of wand.image.Image, not )r  )r  r=   r  r  r   rA  r   ZMagickSteganoImager  r  r  )r  	watermarkr  r  r  r  r  stegano  s    
zBaseImage.steganoc             C   s   t | jS )zWStrips an image of all profiles and comments.

        .. versionadded:: 0.2.0
        )r   ZMagickStripImager  )r  r  r  r  rS     s    zBaseImage.stripc             C   sR   t j|d tdk r$t| j|}n*t jtd|d t|}t| j||}|S )aW  Swirls pixels around the center of the image. The larger the degree
        the more pixels will be effected.

        :see: Example of :ref:`swirl`.

        :param degree: Defines the amount of pixels to be effected. Value
                       between ``-360.0`` and ``360.0``.
        :type degree: :class:`numbers.Real`
        :param method: Controls interpolation of the effected pixels. Only
                       available for ImageMagick-7. See
                       :const:`PIXEL_INTERPOLATE_METHODS`.
        :type method: :class:`basestring`

        .. versionadded:: 0.5.7
        )r  i   z$wand.image.PIXEL_INTERPOLATE_METHODS)rc  )	r   rQ  r   r   ZMagickSwirlImager  r#  r6   rp   )r  r  rc  r  ra  r  r  r  swirl"   s    
zBaseImage.swirlc             C   s<   t |tstdt| t| j|j}|r4|| _t|S )a  Repeat tile-image across the width & height of the image.

        .. code:: python

            from wand.image import Image

            with Image(width=100, height=100) as canvas:
                with Image(filename='tile.png') as tile:
                    canvas.texture(tile)
                canvas.save(filename='output.png')

        :param tile: image to repeat across canvas.
        :type tile: :class:`Image <wand.image.BaseImage>`

        .. versionadded:: 0.5.4
        z8Tile image must be an instance of wand.image.Image, not )r  r=   r  r  r   ZMagickTextureImager  r  )r  r  r  r  r  r  texture?   s    
zBaseImage.texture      ?c             C   sP   t j|d || jd 9 }|dkr2t| j|}n| |}t| j||}|S )a  Changes the value of individual pixels based on the intensity
        of each pixel compared to threshold. The result is a high-contrast,
        two color image. It manipulates the image in place.

        :param threshold: threshold as a factor of quantum. A normalized float
                          between ``0.0`` and ``1.0``.
        :type threshold: :class:`numbers.Real`
        :param channel: the channel type.  available values can be found
                        in the :const:`CHANNELS` mapping.  If ``None``,
                        threshold all channels.
        :type channel: :class:`basestring`

        .. versionadded:: 0.3.10

        )r   r   N)r   rQ  r  r   ZMagickThresholdImager  r  ZMagickThresholdImageChannel)r  r   r  r  r  r  r  r  r   Z   s    
zBaseImage.thresholdc             C   s:   |dkr| j }|dkr| j}tj||d t| j||S )a   Changes the size of an image to the given dimensions and removes any
        associated profiles.  The goal is to produce small low cost thumbnail
        images suited for display on the web.

        :param width: the width in the scaled image. default is the original
                      width
        :type width: :class:`numbers.Integral`
        :param height: the height in the scaled image. default is the original
                       height
        :type height: :class:`numbers.Integral`

        .. versionadded:: 0.5.4
        N)r  r  )r  r  r   r[  r   ZMagickThumbnailImager  )r  r  r  r  r  r  	thumbnailx   s    zBaseImage.thumbnailc          
   C   sj   t |trt|}t |tr$t|}tj||d |* | t| j|j|j}W dQ R X W dQ R X |S )aD  Applies a color vector to each pixel in the image.

        :see: Example of :ref:`tint`.

        :param color: Color to calculate midtone.
        :type color: :class:`~wand.color.Color`
        :param alpha: Determine how to blend.
        :type alpha: :class:`~wand.color.Color`

        .. versionadded:: 0.5.3
        )r  rm   N)	r  r   r   r   r  r   ZMagickTintImager  r2  )r  r  rm   r  r  r  r  tint   s    

zBaseImage.tintr  c          	   C   sD  t j||d y|d}W n tk
r8   tdY nX y|d}W n tk
rd   tdY nX tjs|rtd}td}t	| j
}t	| j}d|krt|t|t|t|t| n*t|t|t|t|t| | j|j|j|j|jdd |rtd}td}t	| j
}t	| j}t|t|t|t|t| | j|j|jd	 d
S | jr t }t| j}t| j}	xLt|	D ]@}
t||
 t|||}t|| t|rt| qW t|rt| |   nt| j||}|r<|| _t|S )a  Transforms the image using :c:func:`MagickTransformImage`,
        which is a convenience function accepting geometry strings to
        perform cropping and resizing.  Cropping is performed first,
        followed by resizing.  Either or both arguments may be omitted
        or given an empty string, in which case the corresponding action
        will not be performed. Geometry specification strings are
        defined as follows:

        A geometry string consists of a size followed by an optional offset.
        The size is specified by one of the options below,
        where **bold** terms are replaced with appropriate integer values:

        **scale**\ ``%``
          Height and width both scaled by specified percentage.

        **scale-x**\ ``%x``\ \ **scale-y**\ ``%``
          Height and width individually scaled by specified percentages.
          Only one % symbol is needed.

        **width**
          Width given, height automagically selected to preserve aspect ratio.

        ``x``\ \ **height**
          Height given, width automagically selected to preserve aspect ratio.

        **width**\ ``x``\ **height**
          Maximum values of width and height given; aspect ratio preserved.

        **width**\ ``x``\ **height**\ ``!``
          Width and height emphatically given; original aspect ratio ignored.

        **width**\ ``x``\ **height**\ ``>``
          Shrinks images with dimension(s) larger than the corresponding
          width and/or height dimension(s).

        **width**\ ``x``\ **height**\ ``<``
          Enlarges images with dimensions smaller than the corresponding
          width and/or height dimension(s).

        **area**\ ``@``
          Resize image to have the specified area in pixels.
          Aspect ratio is preserved.

        **X**\ ``:``\ **Y**
          Resize at a given aspect ratio. Common aspect ratios may
          include ``4:3`` for video/tv, ``3:2`` for 35mm film, ``16:9`` for
          HDTV, and ``2.39:1`` for cinema. Aspect ratio can be used with the
          crop parameter, but is only available with ImageMagick version 7.0.8
          or greater.

        The offset, which only applies to the cropping geometry string,
        is given by ``{+-}``\ **x**\ ``{+-}``\ **y**\ , that is,
        one plus or minus sign followed by an **x** offset,
        followed by another plus or minus sign, followed by a **y** offset.
        Offsets are in pixels from the upper left corner of the image.
        Negative offsets will cause the corresponding number of pixels to
        be removed from the right or bottom edge of the image, meaning the
        cropped size will be the computed size minus the absolute value
        of the offset.

        For example, if you want to crop your image to 300x300 pixels
        and then scale it by 2x for a final size of 600x600 pixels,
        you can call::

            image.transform('300x300', '200%')

        This method is a fairly thin wrapper for the C API, and does not
        perform any additional checking of the parameters except insofar as
        verifying that they are of the correct type.  Thus, like the C
        API function, the method is very permissive in terms of what
        it accepts for geometry strings; unrecognized strings and
        trailing characters will be ignored rather than raising an error.

        :param crop: A geometry string defining a subregion of the image
                     to crop to
        :type crop: :class:`basestring`
        :param resize: A geometry string defining the final size of the image
        :type resize: :class:`basestring`

        .. seealso::

           `ImageMagick Geometry Specifications`__
              Cropping and resizing geometry for the ``transform`` method are
              specified according to ImageMagick's geometry string format.
              The ImageMagick documentation provides more information about
              geometry strings.

           __ http://www.imagemagick.org/script/command-line-processing.php#geometry

        .. versionadded:: 0.2.2
        .. versionchanged:: 0.5.0
           Will call :meth:`crop()` followed by :meth:`resize()` in the event
           that :c:func:`MagickTransformImage` is not available.
        .. deprecated:: 0.6.0
           Use :meth:`crop()` and :meth:`resize()` instead.
        )r  r  r  z2crop must only contain ascii-encodable characters.z4resize must only contain ascii-encodable characters.r      :F)r  r  r  r  r1  )r  r  T)r   rR  rx  UnicodeEncodeErrorr  r   ZMagickTransformImager  rs  rh  r  r  r   r  r  ZGetGeometryr  r4  r  r*  NewMagickWandr  r  r.  r   r'  MagickAddImager  r  r  )r  r  r  r  r  r  r  r  Zsrc_wandr*  r)  Ztmp_wandr  r  r  	transform   s~    f








zBaseImage.transformc             C   s$   t jtd|d t| jt|S )a  Transform image's colorspace.

        :param colorspace_type: colorspace_type. available value can be found
                                in the :const:`COLORSPACE_TYPES`
        :type colorspace_type: :class:`basestring`

        .. versionadded:: 0.4.2

        zwand.image.COLORSPACE_TYPES)r  )r   r#  r#   r   ZMagickTransformImageColorspacer  rp   )r  r<  r  r  r  transform_colorspaceW!  s    zBaseImage.transform_colorspacec          	   C   sV   t j||d t|tr t|}t j|d | t| j|j	|||}W dQ R X |S )a3  Makes the color ``color`` a transparent color with a tolerance of
        fuzz. The ``alpha`` parameter specify the transparency level and the
        parameter ``fuzz`` specify the tolerance.

        :param color: The color that should be made transparent on the image,
                      color object
        :type color: :class:`wand.color.Color`
        :param alpha: the level of transparency: 1.0 is fully opaque
                      and 0.0 is fully transparent.
        :type alpha: :class:`numbers.Real`
        :param fuzz: By default target must match a particular pixel color
                     exactly. However, in many cases two colors may differ
                     by a small amount. The fuzz member of image defines how
                     much tolerance is acceptable to consider two colors as the
                     same. For example, set fuzz to 10 and the color red at
                     intensities of 100 and 102 respectively are now
                     interpreted as the same color for the color.
        :type fuzz: :class:`numbers.Real`
        :param invert: Boolean to tell to paint the inverse selection.
        :type invert: :class:`bool`

        .. versionadded:: 0.3.0

        .. versionchanged:: 0.6.3

            Parameter ``fuzz`` type switched from Integral to Real.

        )rm   r   )r  N)
r   rQ  r  r   r   r  r   ZMagickTransparentPaintImager  r2  )r  r  rm   r   r  r  r  r  r  transparent_colork!  s    
zBaseImage.transparent_colorc             C   s   |rt t| jt| }|j| jks2|jdk r:tdt| jd t	dk rVd}nd}t
| jt| | jd|jdd |   d	S )
a  Makes the image transparent by subtracting some percentage of
        the black color channel.  The ``transparency`` parameter specifies the
        percentage.

        :param transparency: the percentage fade that should be performed on
                             the image, from 0.0 to 1.0
        :type transparency: :class:`numbers.Real`

        .. versionadded:: 0.2.0

        r   z=transparency must be a numbers.Real value between 0.0 and 1.0i   r>  r@  r   rn   )r>  r4  r  N)r  r  r  r  r4  r  r   r'  r  r   r  r/   rp   rA  r  )r  transparencytr  r  r  r  transparentize!  s    
zBaseImage.transparentizec             C   s   t | jS )zCreates a vertical mirror image by reflecting the pixels around
        the central x-axis while rotating them 90-degrees.

        .. versionadded:: 0.4.1
        )r   ZMagickTransposeImager  )r  r  r  r  r  !  s    zBaseImage.transposec             C   s   t | jS )zCreates a horizontal mirror image by reflecting the pixels around
        the central y-axis while rotating them 270-degrees.

        .. versionadded:: 0.4.1
        )r   ZMagickTransverseImager  )r  r  r  r  r  !  s    zBaseImage.transversec          	   C   s  |dk}|r^|dkr| d }nt |tr0t|}tj|d | | j|dddd W dQ R X tj|d tj|d |dk	rtj|d	 tt	|d
dd }d
|}t| jtdt| |st |trt|}tj|d d}|j}	t| jt|t|	 t| j|}
|r$|   nb|rt| j}t|d d d|d< t|d d d|d< |d  d8  < |d  d8  < || _|
S )a  Remove solid border from image. Uses top left pixel as a guide
        by default, or you can also specify the ``color`` to remove.

        :param color: the border color to remove.
                      if it's omitted top left pixel is used by default
        :type color: :class:`~wand.color.Color`
        :param fuzz: Defines how much tolerance is acceptable to consider
                     two colors as the same. Value can be between ``0.0``,
                     and :attr:`quantum_range`.
        :type fuzz: :class:`numbers.Real`
        :param reset_coords: Reset coordinates after triming image. Default
                             ``False``.
        :type reset_coords: :class:`bool`
        :param percent_background: Sets how aggressive the trim operation will
                                   be. A value of `0.0` will trim to the
                                   minimal bounding box of all matching color,
                                   and `1.0` to the most outer edge.
        :type percent_background: :class:`numbers.Real`
        :param background_color: Local alias to :attr:`background_color`,
                                 and has the same effect as defining ``color``
                                 parameter -- but much faster.


        .. versionadded:: 0.2.1

        .. versionchanged:: 0.3.0
           Optional ``color`` and ``fuzz`` parameters.

        .. versionchanged:: 0.5.2
           The ``color`` parameter may accept color-compliant strings.

        .. versionchanged:: 0.6.0
           Optional ``reset_coords`` parameter added.

        .. versionchanged:: 0.6.4
           Optional ``percent_background`` & ``background_color`` parameters
           have been added.
        N)r   r   )r  r   rN   )r=  )r   )r1  )percent_backgroundg      ?g        g      Y@z{0:g}%ztrim:percent-background)r1  ztrim:background-colorr   r^   r  )r  r   r   r   r  r  rQ  r,  r	  r
  r  r   r  r  r	   rN  ZMagickTrimImager1  r  rw  )r  r  r   r1  r  r1  Z
use_borderZstr_pbZbc_keyZbc_valr  Zadjusted_coordsr  r  r  trim!  sL    *







zBaseImage.trimc             C   s   t | jS )zxDiscards all duplicate pixels, and rebuilds the image
        as a single row.

        .. versionadded:: 0.5.0
        )r   ZMagickUniqueImageColorsr  )r  r  r  r  unique_colors "  s    zBaseImage.unique_colorsc       	      C   s   t j||||d |dkr0t| j||||}nZ| |}tdk rZt| j|||||}n0t| j|}t| j||||}t| j| |S )ab  Sharpens the image using unsharp mask filter. We convolve the image
        with a Gaussian operator of the given ``radius`` and standard deviation
        (``sigma``). For reasonable results, ``radius`` should be larger than
        ``sigma``. Use a radius of 0 and :meth:`unsharp_mask()` selects
        a suitable radius for you.

        :see: Example of :ref:`unsharp_mask`.

        :param radius: the radius of the Gaussian, in pixels,
                       not counting the center pixel
        :type radius: :class:`numbers.Real`
        :param sigma: the standard deviation of the Gaussian, in pixels
        :type sigma: :class:`numbers.Real`
        :param amount: the percentage of the difference between the original
                       and the blur image that is added back into the original
        :type amount: :class:`numbers.Real`
        :param threshold: the threshold in pixels needed to apply
                          the difference amount.
        :type threshold: :class:`numbers.Real`
        :param channel: Optional color channel to target. See
                        :const:`CHANNELS`
        :type channel: :class:`basestring`

        .. versionadded:: 0.3.4

        .. versionchanged:: 0.5.5
           Added optional ``channel`` argument.

        .. versionchanged:: 0.5.7
           Added default values to match CLI behavior.
        )r  r  rq  r   Ni   )	r   rQ  r   ZMagickUnsharpMaskImager  r  r   ZMagickUnsharpMaskImageChannelr  )	r  r  r  rq  r   r  r  r  r  r  r  r  unsharp_mask*"  s    #


zBaseImage.unsharp_maskc             C   s"   t j||d t| j||||S )a  Creates a soft vignette style effect on the image.

        :see: Example of :ref:`vignette`.

        :param radius: the radius of the Gaussian blur effect.
        :type radius: :class:`numbers.Real`
        :param sigma: the standard deviation of the Gaussian effect.
        :type sigma: :class:`numbers.Real`
        :param x: Number of pixels to offset inward from the top & bottom of
                  the image before drawing effect.
        :type x: :class:`numbers.Integral`
        :param y: Number of pixels to offset inward from the left & right of
                  the image before drawing effect.
        :type y: :class:`numbers.Integral`

        .. versionadded:: 0.5.2
        )r  r  )r   rQ  r   ZMagickVignetteImager  )r  r  r  r  r  r  r  r  vignette_"  s    zBaseImage.vignettec          	   C   sB   |  (}|| |  | j|||d W dQ R X |   dS )a'  Transparentized the supplied ``image`` and places it over the
        current image, with the top left corner of ``image`` at coordinates
        ``left``, ``top`` of the current image.  The dimensions of the
        current image are not changed.

        :param image: the image placed over the current image
        :type image: :class:`wand.image.Image`
        :param transparency: the percentage fade that should be performed on
                             the image, from 0.0 to 1.0
        :type transparency: :class:`numbers.Real`
        :param left: the x-coordinate where `image` will be placed
        :type left: :class:`numbers.Integral`
        :param top: the y-coordinate where `image` will be placed
        :type top: :class:`numbers.Integral`

        .. versionadded:: 0.2.0

        )r  r  N)r  r  r  r6  r  )r  r	  r  r  r  Zwatermark_imager  r  r  r  v"  s
    

zBaseImage.watermarkc             C   sX   t j||d t jtd|d tdk r8t| j||}nt|}t| j|||}|S )a  Creates a ripple effect within the image.

        :see: Example of :ref:`wave`.

        :param amplitude: height of wave form.
        :type amplitude: :class:`numbers.Real`
        :param wave_length: width of wave form.
        :type wave_length: :class:`numbers.Real`
        :param method: pixel interpolation method. Only available with
                       ImageMagick-7. See :const:`PIXEL_INTERPOLATE_METHODS`
        :type method: :class:`basestring`

        .. versionadded:: 0.5.2
        )	amplitudewave_lengthz$wand.image.PIXEL_INTERPOLATE_METHODS)rc  i   )	r   rQ  r#  r6   r   r   ZMagickWaveImager  rp   )r  r  r  rc  r  ra  r  r  r  wave"  s    
zBaseImage.wavec             C   sx   t jdkrd}t|tj||d d|  k r8dkrFn n
|| j9 }d|  k rZdkrhn n
|| j9 }t | j||S )a  Removes noise by applying a `wavelet transform`_.

        .. _`wavelet transform`:
           https://en.wikipedia.org/wiki/Wavelet_transform

        .. warning::

            This class method is only available with ImageMagick 7.0.8-41, or
            greater.

        :see: Example of :ref:`wavelet_denoise`.

        :param threshold: Smoothing limit.
        :type threshold: :class:`numbers.Real`
        :param softness: Attenuate of the smoothing threshold.
        :type softness: :class:`numbers.Real`
        :raises WandLibraryVersionError: If system's version of ImageMagick
                                         does not support this method.

        .. versionadded:: 0.5.5
        Nz8Method requires ImageMagick version 7.0.8-41 or greater.)r   softnessg        g      ?)r   ZMagickWaveletDenoiseImager   r   rQ  r  r  )r  r   r  r  r  r  r  wavelet_denoise"  s    



zBaseImage.wavelet_denoisec             C   s4   d}t dk rt|ntjdkr(t|t| jS )zUses LAB colorspace to apply a white balance to the image.

        .. note::

            Requires ImageMagick-7.0.10-37 or later.

        .. versionadded:: 0.6.4
        z)Requires ImageMagick-7.0.10-37, or later.i
  N)r   r   r   ZMagickWhiteBalanceImager  )r  r  r  r  r  white_balance"  s    

zBaseImage.white_balancec          	   C   sB   t |trt|}tj|d | t| j|j}W dQ R X |S )zForces all pixels above a given color as white. Leaves pixels
        below threshold unaltered.

        :param threshold: Color to be referenced as a threshold.
        :type threshold: :class:`Color`

        .. versionadded:: 0.5.2
        )r   N)	r  r   r   r   r  r   ZMagickWhiteThresholdImager  r2  )r  r   r  r  r  r  white_threshold"  s    
zBaseImage.white_thresholdc             C   sV   d}d}t jdkrtdn6|dkr6t | j|d}nt|trRt | j||j}|S )a  Sets the write mask which prevents pixel-value updates to the image.
        Call this method with a ``None`` argument to clear any previously set
        masks.

        .. warning::
           This method is only available with ImageMagick-7.

        :param clip_mask: Image to reference as blend mask.
        :type clip_mask: :class:`BaseImage`

        .. versionadded:: 0.5.7
        Fr^   NzMethod requires ImageMagick-7.)r   r  r   r  r  r=   )r  r  r  ZWritePixelMaskr  r  r  r|   "  s    



zBaseImage.write_mask)r  )r  r  N)NN)r  r  N)r  )r   r   r   )r\   )r  )r  r  N)rN   )r  r  N)r  r  r  r  )r   r   NNNN)r   r   )N)rK   N)N)NN)NN)ru   rt   )rK   NN)rK   N)NNr   NN)NNNN)F)T)r  NN)N)r   r   NNNNTN)r   )F)r  )r  r  )N)Nr  N)r   r   NNrB  r  )NNr   r   )T)T)Nr   r   r   r   r   )N)N)r  N)r  r  N)rK   )N)Nrl  )T)r  rK   )r   r   NNr  r  N)T)Nr}  r~  )rx   )r  N)r  Nr  N)N)r  Nr  N)N)r  r  )r   r   )r  r  )rx   )r  )N)N)r  r  r  )NNr   N)r  r  r  N)FN)r{  r  N)N)r  r  )NNr  FN)r   N)r  NNrK   )Nr   )Nr   FF)r  r  N)rx   )r  NNN)N)Nr   )NNrK   r   )NNrK   r   )NT)r  N)NN)r   r   )r  r  r  N)r  )Fr  r  )r  r  r   r   )r  r  N)r   r   )r  r  r  )Tr  r  N)r  rK   )r  r  r  )Fr   )r  N)rd   )NNNN)r  rK   )rK   NNN)r   )r  rK   )r  N)NN)NN)r  r  )r   F)Nr  FNN)r  r  r  r  N)r  r  r   r   )r  r   r   )r  r  rK   )r  r  )N(  r  r  r  __doc__r  sequencer  r  r   ZIsMagickWandc_is_resourcer  c_destroy_resourceZMagickGetExceptionc_get_exceptionZMagickClearExceptionc_clear_exception	__slots__r  r  r  r  r  r
  r  r  r  propertyr"  r  setterrG   r*  r+  r1  r7  r:  r;  r  r=  r?  r@  rB  rD  r4  rL  rM  rK  rI  rJ  r  r   rY  rZ  r  r]  r_  rb  rg  ri  rj  rl  rn  r  rq  rr  rw  r~  r  r  r  r  r  r  r  r  r  r  r  r  r  r  rG  rH  r  r  r  r  r  deleterr  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r   r  r  r  r}  r  r  r  r  r  r  r  r0  r  r  r  r  r   r  r  r  r6  r  r  r  r  r  r\  r  r4  r7  r8  r9  r:  r   rs  r=  r>  r?  r@  rA  rO  rP  r[  r]  r  r  r\  ra  r  rd  r  rf  rj  rk  rm  rp  rr  rt  rn  ru  rv  rw  rx  ry  rz  r{  r|  r  rd  r  r  r  r  r  r  r  r  r  ro  r  r  r  r  r   r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  rm  r  r  r  r  r1  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  rS  r  r  r   r  r  r  r  r  r  r  r  r   r  r  r  r  r  r  r	  r
  r|   r  r  r  r  r=   Q  sd  @:18	
			

"				
				
*'!$&),!& " 9*6d/ A4 H K ] 6=   
;
. _Q 1:.$*$ f%		
%&<+1--
&O $," :L#57 8,& 7M	@2%" 8* 3 Xc /$ -&$		 R	 2!r=   c                   s.  e Zd ZdZdZdZdZdZdZd7 fdd	Z	 fddZ
d8ddZd	d
 Zed9ddZed:ddZedd Zedd Zedd Zd;ddZdd Zdd Zdd Zdd Zdd  Zed!d" Zd#d$ Zed%d& Zed'd( Zed)d* Zd<d+d,Z d=d.d/Z!d>d0d1Z"d2d3 Z#d?d5d6Z$  Z%S )@rB   a	  An image object.

    :param image: makes an exact copy of the ``image``
    :type image: :class:`Image`
    :param blob: opens an image of the ``blob`` byte array
    :type blob: :class:`bytes`
    :param file: opens an image of the ``file`` object
    :type file: file object
    :param filename: opens an image of the ``filename`` string. Additional
                     :ref:`read_mods` are supported.
    :type filename: :class:`basestring`
    :param format: forces filename to  buffer. ``format`` to help
                   ImageMagick detect the file format. Used only in
                   ``blob`` or ``file`` cases
    :type format: :class:`basestring`
    :param width: the width of new blank image or an image loaded from raw
                  data.
    :type width: :class:`numbers.Integral`
    :param height: the height of new blank image or an image loaded from
                   raw data.
    :type height: :class:`numbers.Integral`
    :param depth: the depth used when loading raw data.
    :type depth: :class:`numbers.Integral`
    :param background: an optional background color.
                       default is transparent
    :type background: :class:`wand.color.Color`
    :param resolution: set a resolution value (dpi),
                       useful for vectorial formats (like pdf)
    :type resolution: :class:`collections.abc.Sequence`,
                      :Class:`numbers.Integral`
    :param colorspace: sets the stack's default colorspace value before
                       reading any images.
                       See :const:`COLORSPACE_TYPES`.
    :type colorspace: :class:`basestring`
    :param units: paired with ``resolution`` for defining an image's pixel
                  density. See :const:`UNIT_TYPES`.
    :type units: :class:`basestring`

    .. versionadded:: 0.1.5
       The ``file`` parameter.

    .. versionadded:: 0.1.1
       The ``blob`` parameter.

    .. versionadded:: 0.2.1
       The ``format`` parameter.

    .. versionadded:: 0.2.2
       The ``width``, ``height``, ``background`` parameters.

    .. versionadded:: 0.3.0
       The ``resolution`` parameter.

    .. versionadded:: 0.4.2
       The ``depth`` parameter.

    .. versionchanged:: 0.4.2
       The ``depth``, ``width`` and ``height`` parameters can be used
       with the ``filename``, ``file`` and ``blob`` parameters to load
       raw pixel data.

    .. versionadded:: 0.5.0
       The ``pseudo`` parameter.

    .. versionchanged:: 0.5.4
       Read constructor no longer sets "transparent" background by default.
       Use the ``background`` paramater to specify canvas color when reading
       in image.

    .. versionchanged:: 0.5.7
       Added the ``colorspace`` & ``units`` parameter.

    .. versionchanged:: 0.6.3
       Added ``sampling_factors`` parameter for working with YUV streams.

    .. describe:: [left:right, top:bottom]

       Crops the image by its ``left``, ``right``, ``top`` and ``bottom``,
       and then returns the cropped one. ::

           with img[100:200, 150:300] as cropped:
               # manipulated the cropped image
               pass

       Like other subscriptable objects, default is 0 or its width/height::

           img[:, :]        #--> just clone
           img[:100, 200:]  #--> equivalent to img[0:100, 200:img.height]

       Negative integers count from the end (width/height)::

           img[-70:-50, -20:-10]
           #--> equivalent to img[width-70:width-50, height-20:height-10]

       :returns: the cropped image
       :rtype: :class:`Image`

       .. versionadded:: 0.1.2

    Nc                s  ||||f}|||f}t dd |D r8|d k	r8tdtdd ||f D dkrftd|d |   |d krt }tt| 	| |d k	rt
|tstdt| t|j}tt| 	| nt d	d |D r^| j||||	|
|||||d

 |d k	r| j|d n.|d k	r4| j|d n|d k	rJ| j|d t| jtd n^|d k	r|d k	r|d kr| ||| n| ||| |rt| j|}|s|  |d k	r|| _t| | _t| | _ddlm} || | _t| | _W d Q R X |   d S )Nc             s   s   | ]}|d k	V  qd S )Nr  )r  rW  r  r  r  r  #  s    z!Image.__init__.<locals>.<genexpr>z9blank image parameters can't be used with image parameterc             s   s   | ]}|d k	V  qd S )Nr  )r  rW  r  r  r  r  #  s    r   z, zD and image parameters are exclusive each other; use only one at oncez/image must be a wand.image.Image instance, not c             s   s   | ]}|d k	V  qd S )Nr  )r  rW  r  r  r  r  #  s    )
rM   r  rD  rP   r  r  	interlacer  r  r  )file)r,  )r  r  )r8  ) anyr  r  r  allocater   r  superrB   r  r  r=   r  ZCloneMagickWandr  _preamble_readr  MagickSetFormatr	   blankpseudorE  r  r  rE   metadatarH   	artifactsr  r8  rI   profiles)r  r	  r,  r  r  r  rM   r  rD  rP   r  r  r  r  r  r  r  new_argsZ	open_argsr  r  r8  )	__class__r  r  r  #  s\    











zImage.__init__c                s   t t| jddS )Nz- {self.format!r} ({self.width}x{self.height}))r  )r  rB   r  )r  )r"  r  r  r  #  s    
zImage.__repr__c          	   C   s  |rBt |trt|}tj|d | t| j|j W dQ R X |dk	rrtj	t
d|d t
|}t| j| |dk	rtj|d t| j| |dk	rtj|d t| jt| |dk	rtj|d t| jt| t| jdt|  |dk	r(tj	td	|d
 t|}t| j| |dk	rt |tjrbt|dkrbtj| jf|  n(t |tjrt| j|| ntd|	dk	r|	| _|dk	r|dk	rtj||d t| j|| dS )a  Set-up MagickWand properties before reading an image file. The
        properties are unique to the image decoder.

        :param background: Defines the default background color.
        :type background: :class:`Color`, :class:`basestring`
        :param colorspace: Defines what colorspace the decoder should operate
                           in. See :const:`COLORSPACE_TYPES`.
        :type colorspace: :class:`basestring`
        :param depth: Bits per color sample.
        :type depth: :class:`numbers.Integral`
        :param extract: Only decode a sub-region of the image.
        :type extract: :class:`basestring`
        :param format: Defines the decoder image format.
        :type format: :class:`basestring`
        :param height: Defines how high a blank canvas should be. Only used if
                       ``width`` is also defined.
        :type height: :class:`numbers.Integral`
        :param interlace: Defines the interlacing scheme for raw data streams.
                          See :const:`INTERLACE_TYPES`.
        :type interlace: :class:`basestring`
        :param resolution: Defines the pixel density of a scalable formats.
                           PDF & SVG as examples.
        :type resolution: :class:`collections.abc.Sequence`,
                          :class:`numbers.Integral`
        :param sampling_factors: Defines how a YUV might be upsampled.
        :type sampling_factors: :class:`collections.abc.Sequence`,
                                :class:`basestring`
        :param units: Unused.
        :type units: :class:`numbers.Integral`
        :param width: Defines how wide a blank canvas should be. Only used if
                      ``height`` is also defined.
        :type width: :class:`numbers.Intragal`

        .. versionadded:: 0.6.3
        )rM   Nzwand.image.COLORSPACE_TYPES)r  )rD  )rP   )r  s   buffer.zwand.image.INTERLACE_TYPES)r  r^   zBresolution must be a (x, y) pair or an real number of the same x/y)r  r  )r  r   r   r   r  r   r3  r  r2  r#  r#   rp   ZMagickSetColorspacer0  ZMagickSetDepthrR  ZMagickSetExtractr	   r  rV  r0   ZMagickSetInterlaceSchemer   r8  r  r  r  r  r  r  r\  )r  rM   r  rD  rP   r  r  r  r  r  r  r  Zcolorspace_idxZc_interlacer  r  r  r  #  sV    '





zImage._preamble_readc          	   C   s   |  d
}| S Q R X d S )NrC  )convertr  )r  r  r  r  r  
_repr_png_+$  s    zImage._repr_png_c             C   s^  |j }|d }|d }|dkrjtdddddddddd	d

}x|D ]}||kr@|| }P q@W |dkrjtd|dkrt|dkr|d dk rdd|d  }qdd|d  }nd}t|dr|jtj}	n6t|dr| }	n"t|dr|	 }	n|
d\}	}
t|}|dd \}}t }| t|}t|j||t|||	}|sZ||  |S )a  Create an image instance from a :mod:`numpy` array, or any other
        datatype that implements `__array_interface__`__ protocol.

        .. code::

            import numpy
            from wand.image import Image

            matrix = numpy.random.rand(100, 100, 3)
            with Image.from_array(matrix) as img:
                img.save(filename='noise.png')

        Use the optional ``channel_map`` & ``storage`` arguments to specify
        the order of color channels & data size. If ``channel_map`` is omitted,
        this method will will guess ``"RGB"``, or ``"CMYK"`` based on
        array shape. If ``storage`` is omitted, this method will reference the
        array's ``typestr`` value, and raise a :class:`ValueError` if
        storage-type can not be mapped.

        Float values must be normalized between `0.0` and `1.0`, and signed
        integers should be converted to unsigned values between `0` and
        max value of type.

        Instances of :class:`Image` can also be exported to numpy arrays::

            with Image(filename='rose:') as img:
                matrix = numpy.array(img)

        __ https://docs.scipy.org/doc/numpy/reference/arrays.interface.html

        :param array: Numpy array of pixel values.
        :type array: :class:`numpy.array`
        :param channel_map: Color channel layout.
        :type channel_map: :class:`basestring`
        :param storage: Datatype per pixel part.
        :type storage: :class:`basestring`
        :returns: New instance of an image.
        :rtype: :class:`~wand.image.Image`

        .. versionadded:: 0.5.3
        .. versionchanged:: 0.6.0
           Input ``array`` now expects the :attr:`shape` property to be defined
           as ```( 'height', 'width', 'channels' )```.
        r  rT   Nr  r  r  r  r  r  )
u1i1u2i2Zu4i4u8i8Zf4Zf8z!Unable to determine storage type.r  r^   r  rB  r   ZCMYKAr  r  tobytestostringr  )r"  r  r  r  hasattrr  Zdata_asr  r,  r-  r  r:   rp   r   r  r=   ZMagickConstituteImager  r	   r  )r  arrayr  rC  Zarr_itrr  rT   Zstorage_maptokenZdata_ptrrf  Zstorage_idxr  r  r  instancer  r  r  r  
from_array/$  sR    .








zImage.from_arrayc             K   s^  d}|  }|j f | |dk	rt|tr^ttdr^t|dr^t| |j}t	|j
|}n&tt|ddsxtdn| }d}|dk	rt|tjstdt| t|tsd|}t|j
|t|}n|dk	rt|}t|j
|}|s|  d}t|nN|d	}	|	dk	r&|	|_t||_t||_d
dl m!}
 |
||_ t"||_#|S )a  Ping image header into Image() object, but without any pixel data.
        This is useful for inspecting image meta-data without decoding the
        whole image.

        :param blob: reads an image from the ``blob`` byte array
        :type blob: :class:`bytes`
        :param file: reads an image from the ``file`` object
        :type file: file object
        :param filename: reads an image from the ``filename`` string
        :type filename: :class:`basestring`
        :param resolution: set a resolution value (DPI),
                           useful for vector formats (like PDF)
        :type resolution: :class:`collections.abc.Sequence`,
                          :class:`numbers.Integral`
        :param format: suggest image file format when reading from a ``blob``,
                       or ``file`` property.
        :type format: :class:`basestring`

        .. versionadded:: 0.5.6

        Nfdopenr  r  zUfile must be a readable file object, but the given object does not have read() methodzblob must be iterable, not r"  zMagickPingImage returns false, but did raise ImageMagick exception. This can occur when a delegate is missing, or returns EXIT_SUCCESS without generating a raster.r  r   )r8  )$r  r  r   r.  r   r3  filenor  r   ZMagickPingImageFiler  callabler  r  r  r   r  r  r
   r  ZMagickPingImageBlobr  r   ZMagickPingImager  r   r  r  rE   r  rH   r  r  r8  rI   r   )r  r  r  r,  r  r  r1  fdr  r  r8  r  r  r  ping$  sF    










z
Image.pingc             C   s\   t |tstdt| t |ts4tdt| t|j|j}|sP|  | t|S )a8  Create a new stereogram image from two existing images.

        :see: Example of :ref:`stereogram`.

        :param left: Left-eye image.
        :type left: :class:`wand.image.Image`
        :param right: Right-eye image.
        :type right: :class:`wand.image.Image`

        .. versionadded:: 0.5.4
        z8Left image must be in instance of wand.image.Image, not z9Right image must be in instance of wand.image.Image, not )r  r=   r  r  r   ZMagickStereoImager  r  )r  r  r2  r  r  r  r  
stereogram$  s    

zImage.stereogramc             C   s"   | j dk}t| j}|o |dkS )N)z	image/gifzimage/x-gifr   )mimetyper   r.  r  )r  Zis_gifframesr  r  r  r*  $  s    
zImage.animationc             C   s4   d}t t| j}|r0tt|}t |}|S )z(:class:`basestring`) The MIME type of the image
        e.g. ``'image/jpeg'``, ``'image/png'``.

        .. versionadded:: 0.1.7

        N)r   ZMagickToMimer	   r  r   r  rO  r{  )r  mtyperpr  r  r  r9  $  s    
zImage.mimetypec          	   C   sr   t j||d |dkr td}nt|tr2t|}t j|d |& t| j|||j	}|sd| 
  W dQ R X | S )a  Creates blank image.

        :param width: the width of new blank image.
        :type width: :class:`numbers.Integral`
        :param height: the height of new blank image.
        :type height: :class:`numbers.Integral`
        :param background: an optional background color.
                           default is transparent
        :type background: :class:`wand.color.Color`
        :returns: blank image
        :rtype: :class:`Image`

        .. versionadded:: 0.3.0

        )r  r  NrU   )rM   )r   r0  r   r  r   r  r   ZMagickNewImager  r2  r  )r  r  r  rM   r  r  r  r  r  $  s    

zImage.blankc             C   s   t | j dS )zClears resources associated with the image, leaving the image blank,
        and ready to be used with new image.

        .. versionadded:: 0.3.0

        N)r   ZClearMagickWandr  )r  r  r  r  r   %  s    zImage.clearc             C   s   |    dS )zCloses the image explicitly. If you use the image object in
        :keyword:`with` statement, it was called implicitly so don't have to
        call it.

        .. note::

           It has the same functionality of :attr:`destroy()` method.

        N)destroy)r  r  r  r  rm   %  s    
zImage.closec             C   s   t |tstdt| |dkr*tdd}t|}tdkrPt	| j
|}n4tjrft| j
|}ntj	r|t	| j
|}ntd|s|   tt|dS )a  Generates new images showing the delta pixels between
        layers. Similar pixels are converted to transparent.
        Useful for debugging complex animations. ::

            with img.compare_layers('compareany') as delta:
                delta.save(filename='framediff_%02d.png')

        .. note::

            May not work as expected if animations are already
            optimized.

        :param method: Can be ``'compareany'``,
                       ``'compareclear'``, or ``'compareoverlay'``
        :type method: :class:`basestring`
        :returns: new image stack.
        :rtype: :class:`Image`

        .. versionadded:: 0.5.0
        z5method must be a string from IMAGE_LAYER_METHOD, not )r1  r2  r3  zDmethod can only be 'compareany', 'compareclear', or 'compareoverlay'Ni   z8MagickCompareImageLayers method not available on system.)r	  )r  r   r  r  r  r.   rp   r   r   ZMagickCompareImagesLayersr  ZMagickCompareImageLayersr  r  rB   r=   )r  rc  r  rp  r  r  r  compare_layers,%  s"    

zImage.compare_layersc             C   s   |   }||_|S )a  Converts the image format with the original image maintained.
        It returns a converted image instance which is new. ::

            with img.convert('png') as converted:
                converted.save(filename='converted.png')

        :param format: image format to convert to
        :type format: :class:`basestring`
        :returns: a converted image
        :rtype: :class:`Image`
        :raises ValueError: when the given ``format`` is unsupported

        .. versionadded:: 0.1.6

        )r  r  )r  r  r  r  r  r  r#  V%  s    zImage.convertc             C   s.   ddl m} | j}||  }d|t|S )ac  Generate a base64 `data-url`_ string from the loaded image.
        Useful for converting small graphics into ASCII strings for HTML/CSS
        web development.

        .. _data-url: https://en.wikipedia.org/wiki/Data_URI_scheme

        :returns: a data-url formated string.
        :rtype: :class:`basestring`

        .. versionadded:: 0.6.3
        r   )	b64encodezdata:{0};base64,{1})base64r?  r9  r  r  r   )r  r?  Z	mime_typeZ
base_bytesr  r  r  data_urlj%  s    zImage.data_urlc             C   s"   t |tstdt| j|jS )a  Copies a given image on to the image stack. By default, the added
        image will be append at the end of the stack, or immediately after
        the current image iterator defined by :meth:`~BaseImage.iterator_set`.
        Use :meth:`~BaseImage.iterator_reset` before calling this method to
        insert the new image before existing images on the stack.

        :param image: raster to add.
        :type image: :class:`Image`

        .. versionadded:: 0.6.7
        z*image must be instance of wand.image.Image)r  rB   r  r   r  r  )r  r	  r  r  r  	image_add{%  s    
zImage.image_addc             C   s(   t | j}|s|   dS tt|S )zGenerate & return a clone of a single image at the current
        image-stack index.

        .. versionadded:: 0.6.7
        N)r   ZMagickGetImager  r  rB   r=   )r  r  r  r  r  	image_get%  s
    zImage.image_getc             C   s   t | jS )zdRemove an image from the image-stack at the current index.

        .. versionadded:: 0.6.7
        )r   ZMagickRemoveImager  )r  r  r  r  image_remove%  s    zImage.image_removec             C   s,   t |tstddt| t| j|jS )zOverwrite current image on the image-stack with given image.

        :param image: Wand instance of images to write to stack.
        :type image: :class:`wand.image.Image`

        .. versionadded:: 0.6.7
        z.image must be an instance of wand.image.Image,z not )r  rB   r  r  r   ZMagickSetImager  )r  r	  r  r  r  	image_set%  s    	
zImage.image_setc          
   C   s   t j|d t j|d |  }| | |  B}| | |  $}| | | | | | W dQ R X W dQ R X | | dS )a  Swap two images on the image-stack.

        :param i: image index to replace with ``j``
        :type i: :class:`numbers.Integral`
        :param j: image index to replace with ``i``
        :type j: :class:`numbers.Integral`

        .. versionadded:: 0.6.7
        )r)  )jN)r   rA  rv  r|  rC  rE  )r  r)  rF  r   rW  br  r  r  
image_swap%  s    





zImage.image_swapc          	   C   s   |dk	r"|  |
}| S Q R X t| j t }d}t| jdkr`t| jt	|}nt
| jt	|}|r|jrt||j}t|}|S |   dS )aB  Makes the binary string of the image.

        :param format: the image format to write e.g. ``'png'``, ``'jpeg'``.
                       it is omittable
        :type format: :class:`basestring`
        :returns: a blob (bytes) string
        :rtype: :class:`bytes`
        :raises ValueError: when ``format`` is invalid

        .. versionchanged:: 0.1.6
           Removed a side effect that changes the image :attr:`format`
           silently.

        .. versionadded:: 0.1.5
           The ``format`` parameter became optional.

        .. versionadded:: 0.1.1

        Nr   )r#  r  r   r&  r  r  rh  r.  ZMagickGetImagesBlobr  r'  r4  rO  rP  r  )r  r  Z	convertedr*  r+  r,  r  r  r  r  %  s     

zImage.make_blobxc:c             C   sX   t j||d t j|d t| j||}|s6|   t| jt|}|sT|   dS )a  Creates a new image from ImageMagick's internal protocol coders.

        :param width: Total columns of the new image.
        :type width: :class:`numbers.Integral`
        :param height: Total rows of the new image.
        :type height: :class:`numbers.Integral`
        :param pseudo: The protocol & arguments for the pseudo image.
        :type pseudo: :class:`basestring`

        .. versionadded:: 0.5.0
        )r  r  )r  N)	r   r0  rR  r   r\  r  r  MagickReadImager   )r  r  r  r  r  r  r  r  r  %  s    zImage.pseudoc             C   s,  d}| j ||||||	|
|||d
 |dk	rt|trjttdrjt|drjt| |j}t	| j
|}n&tt|ddstdn| }d}|dk	rt|tjstdt| t|tsd|}t| j
|t|}n|dk	rt|}t| j
|}|s|   d	}t|n|dk	r(|| _dS )
a	  Read new image into Image() object.

        :param blob: reads an image from the ``blob`` byte array
        :type blob: :class:`bytes`
        :param file: reads an image from the ``file`` object
        :type file: file object
        :param filename: reads an image from the ``filename`` string.
                         Additional :ref:`read_mods` are supported.
        :type filename: :class:`basestring`
        :param background: set default background color.
        :type background: :class:`Color`, :class:`basestring`
        :param colorspace: set default colorspace.
                           See :const:`COLORSPACE_TYPES`.
        :type colorspace: :class:`basestring`
        :param depth: sets bits per color sample. Usually ``8``, or ``16``.
        :type depth: :class:`numbers.Integral`
        :param format: sets which image decoder to read with. Helpful when
                       reading ``blob`` data with ambiguous headers.
        :type format: :class:`basestring`
        :param height: used with ``width`` to define the canvas size. Useful
                       for reading image streams.
        :type height: :class:`numbers.Integral`
        :param interlace: Defines the interlacing scheme for raw data streams.
                          See :const:`INTERLACE_TYPES`.
        :type interlace: :class:`basestring`
        :param resolution: set a resolution value (DPI),
                           useful for vectorial formats (like PDF)
        :type resolution: :class:`collections.abc.Sequence`,
                          :class:`numbers.Integral`
        :param sampling_factors: set up/down stampling factors for YUV data
                                 stream. Usually ``"4:2:2"``
        :type sampling_factors: :class:`collections.abc.Sequence`,
                                :class:`basestring`
        :param units: used with ``resolution``, can either be
                     ``'pixelperinch'``, or ``'pixelpercentimeter'``.
        :type units: :class:`basestring`
        :param width: used with ``height`` to define the canvas size. Useful
                      for reading image streams.
        :type width: :class:`numbers.Integral`

        .. versionadded:: 0.3.0

        .. versionchanged:: 0.5.7
           Added ``units`` parameter.

        .. versionchanged:: 0.6.3
           Added, or documented, optional pre-read parameters:
           ``background``, ``colorspace``, ``depth``, ``format``, ``height``,
           ``interlace``, ``sampling_factors``, & ``width``.
        N)
rM   r  rD  rP   r  r  r  r  r  r  r3  r  r  zUfile must be a readable file object, but the given object does not have read() methodzblob must be iterable, not r"  zMagickReadImage returns false, but did not raise ImageMagick  exception. This can occur when a delegate is missing, or returns EXIT_SUCCESS without generating a raster.)r  r  r   r.  r   r3  r4  r  r   ZMagickReadImageFiler  r5  r  r  r  r   r  r  r
   r  ZMagickReadImageBlobr  r   rJ  r  r   r  )r  r  r  r,  rM   r  rD  rP   r  r  r  r  r  r  r  r  r6  r  r  r  r  r  &  s>    6





z
Image.readc             C   s0   x"| j jD ]}t|dr
|  q
W g | j _dS )zRemove any previously allocated :class:`~wand.sequence.SingleImage`
        instances in :attr:`sequence` attribute.

        .. versionadded:: 0.6.0
        r=  N)r  Z	instancesr.  r=  )r  r1  r  r  r  r  a&  s    
zImage.reset_sequenceTc             C   sj  |dkr|dkrt dnJ|dk	r8|dk	r8t dn.|dk	rt|trZt d|nt|trttdrt| |j	}t
| jdkrt
| j|}nt
| j|}t| |s|   n.tt|ddst dt| ||   npt|tst|d	st d
t| t|}t
| jdkrJt
| j||}nt
| j|}|sf|   dS )a  Saves the image into the ``file`` or ``filename``. It takes
        only one argument at a time.

        :param file: a file object to write to
        :type file: file object
        :param filename: a filename string to write to
        :type filename: :class:`basestring`
        :param adjoin: write all images to a single multi-image file. Only
                       available if file format supports frames, layers, & etc.
        :type adjoin: :class:`bool`

        .. versionadded:: 0.1.1

        .. versionchanged:: 0.1.5
           The ``file`` parameter was added.

        .. versionchanged:: 6.0.0
           The ``adjoin`` parameter was added.

        Nzexpected an argumentz*expected only one argument; but two passedz_file must be a writable file object, but {0!r} is a string; did you want .save(filename={0!r})?r3  r   writezJfile must be a writable file object, but it does not have write() method: 
__fspath__zfilename must be a string, not )r  r  r   r  r   r.  r   r3  r4  r  r   r.  r  ZMagickWriteImagesFileZMagickWriteImageFileZfflushr  r5  r  r  rK  r  r   ZMagickWriteImagesZMagickWriteImage)r  r  r  Zadjoinr6  r  r  r  r  savel&  s<    



z
Image.save)NNNNNNNNNNNNNNNN)NNNNNNNNNNN)NN)NNN)N)N)rI  )NNNNNNNNNNNNNN)NNT)&r  r  r  r  r  r  r  r  r   r  r  r  r$  classmethodr2  r7  r8  r  r*  r9  r  r   rm  r>  r#  rA  r  rB  rC  rD  rE  rH  r  r  r  r  rM  __classcell__r  r  )r"  r  rB   #  sV   d    7   
T\@
	*
'
   
\rB   c               @   sX   e Zd ZdZejZejZej	Z
ejZdddZdd Zdd Zdd	d
ZeZdd ZdS )rD   a  Row iterator for :class:`Image`. It shouldn't be instantiated
    directly; instead, it can be acquired through :class:`Image` instance::

        assert isinstance(image, wand.image.Image)
        iterator = iter(image)

    It doesn't iterate every pixel, but rows. For example::

        for row in image:
            for col in row:
                assert isinstance(col, wand.color.Color)
                print(col)

    Every row is a :class:`collections.abc.Sequence` which consists of
    one or more :class:`wand.color.Color` values.

    :param image: the image to get an iterator
    :type image: :class:`Image`

    .. versionadded:: 0.1.3

    Nc          	   C   s   |d k	r|d k	rt d|  p |d k	r\t|tsDt dt| t|j| _|j	| _	n0t|t
svt dt| t|j| _|j	| _	W d Q R X |   d| _d S )Nz$it takes only one argument at a timez*expected a wand.image.Image instance, not z-expected a wand.image.Iterator instance, not r   )r  r  r  rB   r  r   ZNewPixelIteratorr  r2  r  rD   ZClonePixelIteratorr  cursor)r  r	  r  r  r  r  r  &  s     



zIterator.__init__c             C   s   | S )Nr  )r  r  r  r  r
  &  s    zIterator.__iter__c             C   sX   t j|d || jkrtd|| _|dkr:t| j nt| j|d sT| 	  d S )N)r  zcan not be greater than heightr   r   )
r   r[  r  r  rP  r   ZPixelSetFirstIteratorRowr2  ZPixelSetIteratorRowr  )r  r  r  r  r  r  &  s    
zIterator.seekc             C   s   | j | jkr|   t |  j d7  _ t }t| jt	|}|d krd g|j
 }x$t|j
D ]}t|| ||< qdW |S |rt|| S d S )Nr   )rP  r  r=  StopIterationr  rh  r   ZPixelGetNextIteratorRowr2  r  r4  r   r   r/  )r  r  r  pixelsZr_pixelsr  r  r  __next__&  s    zIterator.__next__c             C   s   t | | dS )z#Clones the same iterator.

        )r  )r  )r  r  r  r  r  &  s    zIterator.clone)NN)N)r  r  r  r  r   ZIsPixelIteratorr  ZDestroyPixelIteratorr  ZPixelGetIteratorExceptionr  ZPixelClearIteratorExceptionr  r  r
  r  rS  r  r  r  r  r  r  rD   &  s   

rD   c               @   s$   e Zd ZdZdd Zedd ZdS )rC   zxThe mixin class to maintain a weak reference to the parent
    :class:`Image` object.

    .. versionadded:: 0.3.0

    c             C   s*   t |tstdt| t|| _d S )Nz.expected a wand.image.BaseImage instance, not )r  r=   r  r  weakrefref_image)r  r	  r  r  r  r  '  s    
zImageProperty.__init__c             C   s&   |   }|dk	r|S td| dS )aV  (:class:`Image`) The parent image.

        It ensures that the parent :class:`Image`, which is held in a weak
        reference, still exists.  Returns the dereferenced :class:`Image`
        if it does exist, or raises a :exc:`ClosedImageError` otherwise.

        :exc: `ClosedImageError` when the parent Image has been destroyed

        Nz(parent Image of {0!r} has been destroyed)rV  r@   r  )r  r	  r  r  r  r	  '  s
    zImageProperty.imageN)r  r  r  r  r  r  r	  r  r  r  r  rC   &  s   rC   c               @   s8   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d ZdS )rF   a*  Free-form mutable mapping of global internal settings.

    .. versionadded:: 0.3.0

    .. versionchanged:: 0.5.0
       Remove key check to :const:`OPTIONS`. Image properties are specific to
       vendor, and this library should not attempt to manage the 100+ options
       in a whitelist.
    c             C   s   t tS )N)r  OPTIONS)r  r  r  r  r
  *'  s    zOptionDict.__iter__c             C   s   t tS )N)r  rW  )r  r  r  r  r  -'  s    zOptionDict.__len__c             C   sN   t j|d d}t| jjt|}|rBtt	|}t
|}nt||S )N)r  r"  )r   rR  r   ZMagickGetOptionr	  r  r	   r   r  rO  rP  KeyError)r  r  opt_strZopt_pr  r  r  r  0'  s    zOptionDict.__getitem__c             C   s0   t j||d | j}t|jt|t| d S )N)r  r4  )r   rR  r	  r   r&  r  r	   )r  r  r4  r	  r  r  r  r  ;'  s    zOptionDict.__setitem__c             C   s   d| |< d S )Nr  r  )r  r  r  r  r  __delitem__@'  s    zOptionDict.__delitem__N)	r  r  r  r  r
  r  r  r  rZ  r  r  r  r  rF   '  s   	rF   c                   sH   e Zd ZdZ fddZdd Zdd Zdd	 Zd
d Zdd Z	  Z
S )rE   az  Class that implements dict-like read-only access to image metadata
    like EXIF or IPTC headers. Most WRITE encoders will ignore properties
    assigned here.

    :param image: an image instance
    :type image: :class:`Image`

    .. note::

       You don't have to use this by yourself.
       Use :attr:`Image.metadata` property instead.

    .. versionadded:: 0.3.0

    c                s.   t |tstdt| tt| | d S )Nz*expected a wand.image.Image instance, not )r  rB   r  r  r  rE   r  )r  r	  )r"  r  r  r  U'  s    
zMetadata.__init__c             C   sR   t j|d | j}d}t|jt|}|rFtt	|}t
|}nt||S )z
        :param k: Metadata header name string.
        :type k: :class:`basestring`
        :returns: a header value string
        :rtype: :class:`str`
        )r  r"  )r   rR  r	  r   r  r  r	   r   r  rO  rP  rX  )r  re  r	  r4  vpr  r  r  r  ['  s    zMetadata.__getitem__c             C   s<   t j||d | j}t|jt|t|}|s8|  |S )z
        :param k: Metadata header name string.
        :type k: :class:`basestring`
        :param v: Value to assign.
        :type v: :class:`basestring`

        .. versionadded: 0.5.0
        )r  r4  )r   rR  r	  r   r  r  r	   r  )r  re  r  r	  r  r  r  r  r  m'  s    	zMetadata.__setitem__c             C   s4   t j|d | j}t|jt|}|s0|  dS )z}
        :param k: Metadata header name string.
        :type k: :class:`basestring`

        .. versionadded: 0.5.0
        )r  N)r   rR  r	  r   ZMagickDeleteImagePropertyr  r	   r  )r  re  r	  r  r  r  r  rZ  }'  s
    zMetadata.__delitem__c                sH   | j }t }t|jd|  fddt|jD }t  t	|S )Nr"  c                s   g | ]}t t | qS r  )r   r  rO  )r  r)  )props_pr  r  r%  '  s    z%Metadata.__iter__.<locals>.<listcomp>)
r	  r  rh  r   MagickGetImagePropertiesr  r   r4  rP  r  )r  r	  numpropsr  )r\  r  r
  '  s    
zMetadata.__iter__c             C   s.   | j }t }t|jd|}t|}|jS )Nr"  )r	  r  rh  r   r]  r  rP  r4  )r  r	  r^  r\  r  r  r  r  '  s
    
zMetadata.__len__)r  r  r  r  r  r  r  rZ  r
  r  rO  r  r  )r"  r  rE   D'  s   rE   c                   sH   e Zd ZdZ fddZdd Zdd Zdd	 Zd
d Zdd Z	  Z
S )rH   aC  Splay tree to map image artifacts. Values defined here
    are intended to be used elseware, and will not be written
    to the encoded image.

    For example::

        # Omit timestamp from PNG file headers.
        with Image(filename='input.png') as img:
            img.artifacts['png:exclude-chunks'] = 'tIME'
            img.save(filename='output.png')

    :param image: an image instance
    :type image: :class:`Image`

    .. note::

       You don't have to use this by yourself.
       Use :attr:`Image.artifacts` property instead.

    .. versionadded:: 0.5.0
    c                s.   t |tstdt| tt| | d S )Nz*expected a wand.image.Image instance, not )r  rB   r  r  r  rH   r  )r  r	  )r"  r  r  r  '  s    
zArtifactTree.__init__c             C   s   t j|d | j}d}t|jt|}|rDtt	|}t
|}t|dk rt|jt|}|rtt	|}t
|}nd}|S )z
        :param k: Metadata header name string.
        :type k: :class:`basestring`
        :returns: a header value string
        :rtype: :class:`str`

        .. versionadded: 0.5.0
        )r  r"  r   N)r   rR  r	  r   ZMagickGetImageArtifactr  r	   r   r  rO  rP  r  r  )r  re  r	  vsr[  r  r  r  r  '  s    	
zArtifactTree.__getitem__c             C   s<   t j||d | j}t|jt|t|}|s8|  |S )z
        :param k: Metadata header name string.
        :type k: :class:`basestring`
        :param v: Value to assign.
        :type v: :class:`basestring`

        .. versionadded: 0.5.0
        )r  r4  )r   rR  r	  r   r  r  r	   r  )r  re  r  r	  r  r  r  r  r  '  s    	zArtifactTree.__setitem__c             C   s4   t j|d | j}t|jt|}|s0|  dS )z}
        :param k: Metadata header name string.
        :type k: :class:`basestring`

        .. versionadded: 0.5.0
        )r  N)r   rR  r	  r   ZMagickDeleteImageArtifactr  r	   r  )r  re  r	  r  r  r  r  rZ  '  s
    zArtifactTree.__delitem__c                sJ   | j }td}t|jd|  fddt|jD }t  t	|S )Nr   r"  c                s   g | ]}t t | qS r  )r   r  rO  )r  r)  )art_pr  r  r%  '  s    z)ArtifactTree.__iter__.<locals>.<listcomp>)
r	  r  rh  r   MagickGetImageArtifactsr  r   r4  rP  r  )r  r	  r^  r_  r  )ra  r  r
  '  s    

zArtifactTree.__iter__c             C   s0   | j }td}t|jd|}t|}|jS )Nr   r"  )r	  r  rh  r   rb  r  rP  r4  )r  r	  r^  ra  r  r  r  r  '  s
    

zArtifactTree.__len__)r  r  r  r  r  r  r  rZ  r
  r  rO  r  r  )r"  r  rH   '  s   rH   c                   sH   e Zd ZdZ fddZdd Zdd Zdd	 Zd
d Zdd Z	  Z
S )rI   a  The mapping table of embedded image profiles.

    Use this to get, set, and delete whole profile payloads on an image. Each
    payload is a raw binary string.

    For example::

        with Image(filename='photo.jpg') as img:
            # Extract EXIF
            with open('exif.bin', 'wb') as payload:
                payload.write(img.profiles['exif'])
            # Import ICC
            with open('color_profile.icc', 'rb') as payload:
                img.profiles['icc'] = payload.read()
            # Remove XMP
            del imp.profiles['xmp']

    .. seealso::

        `Embedded Image Profiles`__ for a list of supported profiles.

        __ https://imagemagick.org/script/formats.php#embedded

    .. versionadded:: 0.5.1
    c                s.   t |tstdt| tt| | d S )Nz*expected a wand.image.Image instance, not )r  rB   r  r  r  rI   r  )r  r	  )r"  r  r  r  (  s    
zProfileDict.__init__c             C   s:   t j|d td}t| jjt||}t	|}d S )N)r  r   )
r   rR  r  rh  r   ZMagickRemoveImageProfiler	  r  r	   rP  )r  re  r^  	profile_pr  r  r  rZ  (  s
    

zProfileDict.__delitem__c             C   sV   t j|d td}d }t| jjt||}|j	dkrRt
||j	}t|}|S )N)r  r   )r   rR  r  rh  r   ZMagickGetImageProfiler	  r  r	   r4  rO  rP  )r  re  r^  Zreturn_profilerc  r  r  r  r  $(  s    



zProfileDict.__getitem__c                sF   t d}t| jjd|  fddt|jD }t  t	|S )Nr   r"  c                s   g | ]}t t | qS r  )r   r  rO  )r  r)  )propr  r  r%  2(  s    z(ProfileDict.__iter__.<locals>.<listcomp>)
r  rh  r   MagickGetImageProfilesr	  r  r   r4  rP  r  )r  r^  r   r  )rd  r  r
  /(  s
    

zProfileDict.__iter__c             C   s,   t d}t| jjd|}t|}|jS )Nr   r"  )r  rh  r   re  r	  r  rP  r4  )r  r^  Z
profiles_pr  r  r  r  6(  s    

zProfileDict.__len__c             C   sT   t j|d t|ts&tdt| t| jj	t
||t|}|sP| j  d S )N)r  z#value must be a binary string, not )r   rR  r  r
   r  r  r   ZMagickSetImageProfiler	  r  r	   r  r  )r  re  r  r  r  r  r  r  <(  s    

zProfileDict.__setitem__)r  r  r  r  r  rZ  r  r
  r  r  rO  r  r  )r"  r  rI   '  s   rI   c               @   s(   e Zd ZdZdd Zdd Zdd ZdS )	r?   a4  The mapping table of separated images of the particular channel
    from the image.

    :param image: an image instance
    :type image: :class:`Image`

    .. note::

       You don't have to use this by yourself.
       Use :attr:`Image.channel_images` property instead.

    .. versionadded:: 0.3.0

    c             C   s   t tS )N)r  r"   )r  r  r  r  r
  V(  s    zChannelImageDict.__iter__c             C   s   t tS )N)r  r"   )r  r  r  r  r  Y(  s    zChannelImageDict.__len__c             C   sj   t | }| j }tjr(t|j|}nt|j|}|sfy|  W n tk
rd   |	   Y nX |S )N)
r"   r	  r  r   ZMagickSeparateImageChannelr  ZMagickSeparateImager  r   rm  )r  r  r  imgZ	succeededr  r  r  r  \(  s    
zChannelImageDict.__getitem__N)r  r  r  r  r
  r  r  r  r  r  r  r?   F(  s   r?   c               @   s(   e Zd ZdZdd Zdd Zdd ZdS )	r>   a  The mapping table of channels to their depth.

    :param image: an image instance
    :type image: :class:`Image`

    .. note::

       You don't have to use this by yourself.
       Use :attr:`Image.channel_depths` property instead.

    .. versionadded:: 0.3.0

    c             C   s   t tS )N)r  r"   )r  r  r  r  r
  {(  s    zChannelDepthDict.__iter__c             C   s   t tS )N)r  r"   )r  r  r  r  r  ~(  s    zChannelDepthDict.__len__c             C   sj   t | }tjr t| jj|}nBd}|dkr<t| jj|}t| jj}|dkrbt| jj| t|S )Nr   )r"   r   ZMagickGetImageChannelDepthr	  r  r  rC  rt  )r  r  r  rD  r  r  r  r  r  (  s    zChannelDepthDict.__getitem__N)r  r  r  r  r
  r  r  r  r  r  r  r>   l(  s   r>   c               @   s@   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d Zdd Z	dS )rA   zSpecialized mapping object to represent color histogram.
    Keys are colors, and values are the number of pixels.

    :param image: the image to get its histogram
    :type image: :class:`BaseImage`

    .. versionadded:: 0.3.0

    c             C   s,   t  | _t|jt | j| _d | _d S )N)	r  rh  r  r   ZMagickGetImageHistogramr  r  rR  counts)r  r	  r  r  r  r  (  s
    
zHistogramDict.__init__c             C   s   | j rt| j | jj| _ d S )N)rR  r   ZDestroyPixelWandsr  r4  )r  r  r  r  __del__(  s    zHistogramDict.__del__c             C   s   | j d kr| jjS t| j S )N)rg  r  r4  r  )r  r  r  r  r  (  s    
zHistogramDict.__len__c             C   s   | j d kr|   t| j S )N)rg  _build_countsr  )r  r  r  r  r
  (  s    
zHistogramDict.__iter__c             C   s:   | j d kr|   t|tr$t|}tj|d | j | S )N)r  )rg  ri  r  r   r   r   r  )r  r  r  r  r  r  (  s    

zHistogramDict.__getitem__c             C   sJ   i | _ x>t| jjD ].}t| j| }t| j| }|| j |< qW d S )N)	rg  r   r  r4  r   ZPixelGetColorCountrR  r   r/  )r  r)  Zcolor_countr  r  r  r  ri  (  s
    zHistogramDict._build_countsN)
r  r  r  r  r  rh  r  r
  r  ri  r  r  r  r  rA   (  s   	rA   c               @   s   e Zd ZdZdZdZdZdZdZdZ	dZ
dZdZdZdZdddZedd Zedd Zed	d
 Zdd Zdd Zdd ZdS )rJ   a  Generic Python wrapper to translate
    :c:type:`CCObjectInfo` structure into a class describing objects found
    within an image. This class is generated by
    :meth:`Image.connected_components()
    <wand.image.BaseImage.connected_components>` method.

    .. versionadded:: 0.5.5
    .. versionchanged:: 0.6.3
        Added :attr:`merge` & :attr:`metric` for ImageMagick 7.0.10
    Nc             C   s6   t |tr| | t |tr2| | | | d S )N)r  r   clone_from_cc_object_infor   clone_from_extra_70A_info)r  	cc_objectr  r  r  r  (  s
    



z!ConnectedComponentObject.__init__c             C   s   | j | jfS )zT(:class:`tuple` (:attr:`width`, :attr:`height`))
        Minimum bounding rectangle.)r  r  )r  r  r  r  r  (  s    zConnectedComponentObject.sizec             C   s   | j | jfS )zd(:class:`tuple` (:attr:`left`, :attr:`top`))
        Position of objects minimum bounding rectangle.)r  r  )r  r  r  r  r  )  s    zConnectedComponentObject.offsetc             C   s   | j | jfS )zO(:class:`tuple` (:attr:`center_x`, :attr:`center_y`))
        Center of object.)center_xcenter_y)r  r  r  r  centroid)  s    z!ConnectedComponentObject.centroidc             C   s   |j | _ |jj| _|jj| _|jj| _|jj| _|jj| _	|jj| _
|j| _tt}t|}t|t|j| t|d| _dS )z<Copy data from :class:`~wand.cdefs.structures.CCObjectInfo`.)rawN)_idZbounding_boxr  r  r  r  r  r  ro  rm  rn  r  r  r  r   create_string_bufferr  r  r  r   r  )r  rl  Z
pinfo_sizeZ
raw_bufferr  r  r  rj  )  s    








z2ConnectedComponentObject.clone_from_cc_object_infoc             C   s8   |j | _ g | _x$t|jD ]}| j|j|  qW dS )zCopy the additional values from CCObjectInfo structure. This is the
        :attr:`merge` & :attr:`metric` properties added in ImageMagick 7.0.10.

        .. versionadded:: 0.6.3
        N)r7  r  rangeZCCMaxMetricsr  )r  rl  r)  r  r  r  rk  ")  s    z2ConnectedComponentObject.clone_from_extra_70A_infoc             C   s   d}|j f d| jji| jS )Nzb{name}({_id}: {width}x{height}+{left}+{top} {center_x:.2f},{center_y:.2f} {area:.0f} {mean_color})name)r  r"  r  __dict__)r  rX  r  r  r  r  -)  s    z!ConnectedComponentObject.__repr__)N)r  r  r  r  rq  r  r  r  r  rm  rn  r  r  r7  r  r  r  r  r  ro  rj  rk  r  r  r  r  r  rJ   (  s&   

rJ   c               @   s   e Zd ZdZdS )r@   zUAn error that rises when some code tries access to an already closed
    image.

    N)r  r  r  r  r  r  r  r  r@   3)  s   r@   )_r  r  r  r  rT  r  r   apir   r   r   r  r   compatr   r	   r
   r   r   r   r   r   r   
exceptionsr   r   r   r   rL  r   r2  r   r   Zcdefs.structuresr   r   r   r   r   r   r  r   r   __all__r    r!   r  r"   r#   r$   r  r%   r&   r'   r(   r)   r*   r+   r,   r-   r.   r/   r0   r1   r2   r3   	frozensetrW  r4   r5   r6   r7   r8   r9   r:   r<   r;   rG   r  r=   rB   rD   objectrC   MutableMappingrF   rE   rH   rI   r  r?   r>   rA   rJ   r@   r  r  r  r  <module>   s  , *!

1
"
j
-
 /
5
"
-
$




                                                             |       V"%VcI&#2r