cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1 | /* |
cristy | 16af1cb | 2009-12-11 21:38:29 +0000 | [diff] [blame] | 2 | Copyright 1999-2010 ImageMagick Studio LLC, a non-profit organization |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 3 | dedicated to making software imaging solutions freely available. |
| 4 | |
| 5 | You may not use this file except in compliance with the License. |
| 6 | obtain a copy of the License at |
| 7 | |
| 8 | http://www.imagemagick.org/script/license.php |
| 9 | |
| 10 | Unless required by applicable law or agreed to in writing, software |
| 11 | distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | See the License for the specific language governing permissions and |
| 14 | limitations under the License. |
| 15 | |
| 16 | MagickCore image composite private methods. |
| 17 | */ |
| 18 | #ifndef _MAGICKCORE_COMPOSITE_PRIVATE_H |
| 19 | #define _MAGICKCORE_COMPOSITE_PRIVATE_H |
| 20 | |
| 21 | #if defined(__cplusplus) || defined(c_plusplus) |
| 22 | extern "C" { |
| 23 | #endif |
| 24 | |
| 25 | /* |
| 26 | ImageMagick Alpha Composite Inline Methods (special export) |
| 27 | */ |
| 28 | |
| 29 | #include "magick/color.h" |
| 30 | #include "magick/image.h" |
| 31 | #include "magick/image-private.h" |
| 32 | |
| 33 | static inline MagickRealType RoundToUnity(const MagickRealType value) |
| 34 | { |
| 35 | return(value < 0.0 ? 0.0 : (value > 1.0) ? 1.0 : value); |
| 36 | } |
| 37 | |
| 38 | static inline MagickRealType MagickOver_(const MagickRealType p, |
| 39 | const MagickRealType alpha,const MagickRealType q,const MagickRealType beta) |
| 40 | { |
| 41 | return((1.0-QuantumScale*alpha)*p+ |
| 42 | (1.0-QuantumScale*beta)*q*QuantumScale*alpha); |
| 43 | } |
| 44 | |
| 45 | static inline void MagickCompositeOver(const PixelPacket *p, |
| 46 | const MagickRealType alpha,const PixelPacket *q,const MagickRealType beta, |
| 47 | PixelPacket *composite) |
| 48 | { |
| 49 | MagickRealType |
| 50 | gamma; |
| 51 | |
| 52 | /* |
| 53 | Compose pixel p over pixel q with the given opacities. |
| 54 | */ |
| 55 | if (alpha == TransparentOpacity) |
| 56 | { |
| 57 | if (composite != q) |
| 58 | *composite=(*q); |
| 59 | return; |
| 60 | } |
| 61 | gamma=1.0-QuantumScale*QuantumScale*alpha*beta; |
| 62 | #if !defined(MAGICKCORE_HDRI_SUPPORT) |
| 63 | composite->opacity=(Quantum) (QuantumRange*(1.0-gamma)+0.5); |
| 64 | gamma=1.0/(gamma <= MagickEpsilon ? 1.0 : gamma); |
| 65 | composite->red=(Quantum) (gamma*MagickOver_((MagickRealType) p->red,alpha, |
| 66 | (MagickRealType) q->red,beta)+0.5); |
| 67 | composite->green=(Quantum) (gamma*MagickOver_((MagickRealType) p->green,alpha, |
| 68 | (MagickRealType) q->green,beta)+0.5); |
| 69 | composite->blue=(Quantum) (gamma*MagickOver_((MagickRealType) p->blue,alpha, |
| 70 | (MagickRealType) q->blue,beta)+0.5); |
| 71 | #else |
| 72 | composite->opacity=(Quantum) (QuantumRange*(1.0-gamma)); |
| 73 | gamma=1.0/(gamma <= MagickEpsilon ? 1.0 : gamma); |
| 74 | composite->red=(Quantum) (gamma*MagickOver_((MagickRealType) p->red,alpha, |
| 75 | (MagickRealType) q->red,beta)); |
| 76 | composite->green=(Quantum) (gamma*MagickOver_((MagickRealType) p->green,alpha, |
| 77 | (MagickRealType) q->green,beta)); |
| 78 | composite->blue=(Quantum) (gamma*MagickOver_((MagickRealType) p->blue,alpha, |
| 79 | (MagickRealType) q->blue,beta)); |
| 80 | #endif |
| 81 | } |
| 82 | |
| 83 | static inline void MagickPixelCompositeOver(const MagickPixelPacket *p, |
| 84 | const MagickRealType alpha,const MagickPixelPacket *q, |
| 85 | const MagickRealType beta,MagickPixelPacket *composite) |
| 86 | { |
| 87 | MagickRealType |
| 88 | gamma; |
| 89 | |
| 90 | /* |
| 91 | Compose pixel p over pixel q with the given opacities. |
| 92 | */ |
| 93 | if (alpha == OpaqueOpacity) |
| 94 | { |
| 95 | *composite=(*p); |
| 96 | return; |
| 97 | } |
| 98 | gamma=1.0-QuantumScale*QuantumScale*alpha*beta; |
| 99 | composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma); |
| 100 | gamma=1.0/(fabs(gamma) <= MagickEpsilon ? 1.0 : gamma); |
| 101 | composite->red=gamma*MagickOver_(p->red,alpha,q->red,beta); |
| 102 | composite->green=gamma*MagickOver_(p->green,alpha,q->green,beta); |
| 103 | composite->blue=gamma*MagickOver_(p->blue,alpha,q->blue,beta); |
| 104 | if (q->colorspace == CMYKColorspace) |
| 105 | composite->index=gamma*MagickOver_(p->index,alpha,q->index,beta); |
| 106 | } |
| 107 | |
| 108 | static inline void MagickPixelCompositePlus(const MagickPixelPacket *p, |
| 109 | const MagickRealType alpha,const MagickPixelPacket *q, |
| 110 | const MagickRealType beta,MagickPixelPacket *composite) |
| 111 | { |
| 112 | MagickRealType |
| 113 | Da, |
anthony | 320be8b | 2010-05-05 06:16:16 +0000 | [diff] [blame] | 114 | gamma, |
| 115 | Sa; |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 116 | |
| 117 | /* |
| 118 | Add two pixels with the given opacities. |
| 119 | */ |
| 120 | Sa=1.0-QuantumScale*alpha; |
| 121 | Da=1.0-QuantumScale*beta; |
| 122 | gamma=RoundToUnity(Sa+Da); /* 'Plus' blending -- not 'Over' blending */ |
| 123 | composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma); |
| 124 | gamma=1.0/(fabs(gamma) <= MagickEpsilon ? 1.0 : gamma); |
| 125 | composite->red=gamma*(Sa*p->red+Da*q->red); |
| 126 | composite->green=gamma*(Sa*p->green+Da*q->green); |
| 127 | composite->blue=gamma*(Sa*p->blue+Da*q->blue); |
| 128 | if (q->colorspace == CMYKColorspace) |
| 129 | composite->index=gamma*(Sa*p->index+Da*q->index); |
| 130 | } |
| 131 | |
| 132 | /* |
| 133 | Blend pixel colors p and q by the amount given. |
| 134 | */ |
| 135 | static inline void MagickPixelCompositeBlend(const MagickPixelPacket *p, |
| 136 | const MagickRealType alpha,const MagickPixelPacket *q, |
| 137 | const MagickRealType beta,MagickPixelPacket *composite) |
| 138 | { |
| 139 | MagickPixelCompositePlus(p,(MagickRealType) (QuantumRange-alpha* |
| 140 | (QuantumRange-p->opacity)),q,(MagickRealType) (QuantumRange-beta* |
cristy | 46f0820 | 2010-01-10 04:04:21 +0000 | [diff] [blame] | 141 | GetAlphaPixelComponent(q)),composite); |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 142 | } |
| 143 | |
| 144 | /* |
| 145 | Blend pixel colors p and q by the amount given and area. |
| 146 | */ |
| 147 | static inline void MagickPixelCompositeAreaBlend(const MagickPixelPacket *p, |
| 148 | const MagickRealType alpha,const MagickPixelPacket *q, |
| 149 | const MagickRealType beta,const MagickRealType area, |
| 150 | MagickPixelPacket *composite) |
| 151 | { |
| 152 | MagickPixelCompositePlus(p,(MagickRealType) QuantumRange-(1.0-area)* |
| 153 | (QuantumRange-alpha),q,(MagickRealType) (QuantumRange-area*(QuantumRange- |
| 154 | beta)),composite); |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 155 | } |
| 156 | |
| 157 | #if defined(__cplusplus) || defined(c_plusplus) |
| 158 | } |
| 159 | #endif |
| 160 | |
| 161 | #endif |