1: <?php
2: /**
3: ##DOC-SIGNATURE##
4:
5: This file is part of WideImage.
6:
7: WideImage is free software; you can redistribute it and/or modify
8: it under the terms of the GNU Lesser General Public License as published by
9: the Free Software Foundation; either version 2.1 of the License, or
10: (at your option) any later version.
11:
12: WideImage is distributed in the hope that it will be useful,
13: but WITHOUT ANY WARRANTY; without even the implied warranty of
14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15: GNU Lesser General Public License for more details.
16:
17: You should have received a copy of the GNU Lesser General Public License
18: along with WideImage; if not, write to the Free Software
19: Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20: **/
21:
22: namespace WideImage;
23:
24: use WideImage\Exception\InvalidImageDimensionException;
25:
26: /**
27: * A class for truecolor image objects
28: *
29: * @package WideImage
30: */
31: class TrueColorImage extends Image
32: {
33: /**
34: * Creates the object
35: *
36: * @param resource $handle
37: */
38: public function __construct($handle)
39: {
40: parent::__construct($handle);
41:
42: $this->alphaBlending(false);
43: $this->saveAlpha(true);
44: }
45:
46: /**
47: * Factory method that creates a true-color image object
48: *
49: * @param int $width
50: * @param int $height
51: * @return \WideImage\TrueColorImage
52: */
53: public static function create($width, $height)
54: {
55: if ($width * $height <= 0 || $width < 0) {
56: throw new InvalidImageDimensionException("Can't create an image with dimensions [$width, $height].");
57: }
58:
59: return new TrueColorImage(imagecreatetruecolor($width, $height));
60: }
61:
62: public function doCreate($width, $height)
63: {
64: return static::create($width, $height);
65: }
66:
67: public function isTrueColor()
68: {
69: return true;
70: }
71:
72: /**
73: * Sets alpha blending mode via imagealphablending()
74: *
75: * @param bool $mode
76: * @return bool
77: */
78: public function alphaBlending($mode)
79: {
80: return imagealphablending($this->handle, $mode);
81: }
82:
83: /**
84: * Toggle if alpha channel should be saved with the image via imagesavealpha()
85: *
86: * @param bool $on
87: * @return bool
88: */
89: public function saveAlpha($on)
90: {
91: return imagesavealpha($this->handle, $on);
92: }
93:
94: /**
95: * Allocates a color and returns its index
96: *
97: * This method accepts either each component as an integer value,
98: * or an associative array that holds the color's components in keys
99: * 'red', 'green', 'blue', 'alpha'.
100: *
101: * @param mixed $R
102: * @param int $G
103: * @param int $B
104: * @param int $A
105: * @return int
106: */
107: public function allocateColorAlpha($R, $G = null, $B = null, $A = null)
108: {
109: if (is_array($R)) {
110: return imageColorAllocateAlpha($this->handle, $R['red'], $R['green'], $R['blue'], $R['alpha']);
111: }
112:
113: return imageColorAllocateAlpha($this->handle, $R, $G, $B, $A);
114: }
115:
116: /**
117: * @see \WideImage\Image#asPalette($nColors, $dither, $matchPalette)
118: */
119: public function asPalette($nColors = 255, $dither = null, $matchPalette = true)
120: {
121: $nColors = intval($nColors);
122:
123: if ($nColors < 1) {
124: $nColors = 1;
125: } elseif ($nColors > 255) {
126: $nColors = 255;
127: }
128:
129: if ($dither === null) {
130: $dither = $this->isTransparent();
131: }
132:
133: $temp = $this->copy();
134:
135: imagetruecolortopalette($temp->handle, $dither, $nColors);
136:
137: if ($matchPalette == true && function_exists('imagecolormatch')) {
138: imagecolormatch($this->handle, $temp->handle);
139: }
140:
141: // The code below isn't working properly; it corrupts transparency on some palette->tc->palette conversions.
142: // Why is this code here?
143: /*
144: if ($this->isTransparent())
145: {
146: $trgb = $this->getTransparentColorRGB();
147: $tci = $temp->getClosestColor($trgb);
148: $temp->setTransparentColor($tci);
149: }
150: /**/
151:
152: $temp->releaseHandle();
153:
154: return new PaletteImage($temp->handle);
155: }
156:
157: /**
158: * Returns the index of the color that best match the given color components
159: *
160: * This method accepts either each component as an integer value,
161: * or an associative array that holds the color's components in keys
162: * 'red', 'green', 'blue', 'alpha'.
163: *
164: * @param mixed $R Red component value or an associative array
165: * @param int $G Green component
166: * @param int $B Blue component
167: * @param int $A Alpha component
168: * @return int The color index
169: */
170: public function getClosestColorAlpha($R, $G = null, $B = null, $A = null)
171: {
172: if (is_array($R)) {
173: return imagecolorclosestalpha($this->handle, $R['red'], $R['green'], $R['blue'], $R['alpha']);
174: }
175:
176: return imagecolorclosestalpha($this->handle, $R, $G, $B, $A);
177: }
178:
179: /**
180: * Returns the index of the color that exactly match the given color components
181: *
182: * This method accepts either each component as an integer value,
183: * or an associative array that holds the color's components in keys
184: * 'red', 'green', 'blue', 'alpha'.
185: *
186: * @param mixed $R Red component value or an associative array
187: * @param int $G Green component
188: * @param int $B Blue component
189: * @param int $A Alpha component
190: * @return int The color index
191: */
192: public function getExactColorAlpha($R, $G = null, $B = null, $A = null)
193: {
194: if (is_array($R)) {
195: return imagecolorexactalpha($this->handle, $R['red'], $R['green'], $R['blue'], $R['alpha']);
196: }
197:
198: return imagecolorexactalpha($this->handle, $R, $G, $B, $A);
199: }
200:
201: /**
202: * @see \WideImage\Image#getChannels()
203: */
204: public function getChannels()
205: {
206: $args = func_get_args();
207:
208: if (count($args) == 1 && is_array($args[0])) {
209: $args = $args[0];
210: }
211:
212: return OperationFactory::get('CopyChannelsTrueColor')->execute($this, $args);
213: }
214:
215: /**
216: * (non-PHPdoc)
217: * @see \WideImage\Image#copyNoAlpha()
218: */
219: public function copyNoAlpha()
220: {
221: $prev = $this->saveAlpha(false);
222: $result = WideImage::loadFromString($this->asString('png'));
223: $this->saveAlpha($prev);
224: //$result->releaseHandle();
225: return $result;
226: }
227:
228: /**
229: * (non-PHPdoc)
230: * @see \WideImage\Image#asTrueColor()
231: * @return TrueColorImage
232: */
233: public function asTrueColor()
234: {
235: return $this->copy();
236: }
237:
238: /**
239: * Calls imageinterlace() using the current handler
240: * @see \WideImage\Image#asTrueColor()
241: * @return TrueColorImage A copy of the image, with imageinterlace() applied
242: */
243: public function asProgressive()
244: {
245: $dest = $this->asTrueColor();
246:
247: imageinterlace($dest->getHandle(), true);
248:
249: return $dest;
250: }
251:
252: /**
253: * Resizes the image proportionally inside the given width and height.
254: * The returned image will have always the specified width and height, and any space will be filled
255: * with the given $fillCollor
256: *
257: * @param int $width Exact width in pixels
258: * @param int $height Exact height in pixels
259: * @param string $fit 'inside' (default), 'outside' or 'fill'
260: * @param string $scale 'down' (default), 'up' or 'any'
261: * @param mixed $alignLeft Left position of the image over the fill space, smart coordinate
262: * @param mixed $alignTop Top position of the image over the fill space, smart coordinate
263: * @param int $mergeOpacity The opacity of the image over the fill space
264: * @param int|array $fillColor RGB color index or array. Background color to fill the resulting image with if it's smaller
265: * than the given size. By default (if null), the top left pixel color will be used.
266: *
267: * @return TrueColorImage A new, resized image
268: */
269: public function resizeInsideRect($width, $height, $fit = 'inside', $scale = 'down', $alignLeft = 'center',
270: $alignTop = 'center', $mergeOpacity = 100, $fillColor = null)
271: {
272:
273: if ($fillColor) {
274: if (is_numeric($fillColor)) {
275: $fillColor = $this->getColorRGB($fillColor);
276: }
277: } else {
278: $fillColor = $this->getColorRGB($this->getColorAt(0, 0));
279: }
280:
281: $rect = \WideImage::createTrueColorImage($width, $height);
282: $rect->fill(0, 0, $rect->allocateColor($fillColor));
283:
284: $img = $this;
285:
286: for ($i = 0; $i < 4; $i++) { //4 times
287: $img = $img->resize($width, $height, $fit, $scale);
288: }
289:
290: return $rect->merge($img, $alignLeft, $alignTop, $mergeOpacity);
291: }
292: }
293:
294: