Blame view

sources/lib/private/image.php 29.5 KB
03e52840d   Kload   Init
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
  <?php
  
  /**
  * ownCloud
  *
  * @author Thomas Tanghus
  * @copyright 2011 Thomas Tanghus <thomas@tanghus.net>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
  * License as published by the Free Software Foundation; either
  * version 3 of the License, or any later version.
  *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
  *
  * You should have received a copy of the GNU Affero General Public
  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
  *
  */
  /**
   * Class for basic image manipulation
   */
  class OC_Image {
  	protected $resource = false; // tmp resource.
31b7f2792   Kload   Upgrade to ownclo...
28
29
30
31
32
33
  	protected $imageType = IMAGETYPE_PNG; // Default to png if file type isn't evident.
  	protected $mimeType = "image/png"; // Default to png
  	protected $bitDepth = 24;
  	protected $filePath = null;
  
  	private $fileInfo;
03e52840d   Kload   Init
34
35
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
36
37
38
  	* Get mime type for an image file.
  	* @param string|null $filePath The path to a local image file.
  	* @return string The mime type if the it could be determined, otherwise an empty string.
03e52840d   Kload   Init
39
  	*/
31b7f2792   Kload   Upgrade to ownclo...
40
  	static public function getMimeTypeForFile($filePath) {
03e52840d   Kload   Init
41
  		// exif_imagetype throws "read error!" if file is less than 12 byte
31b7f2792   Kload   Upgrade to ownclo...
42
43
  		if (filesize($filePath) > 11) {
  			$imageType = exif_imagetype($filePath);
6d9380f96   Cédric Dupont   Update sources OC...
44
  		} else {
31b7f2792   Kload   Upgrade to ownclo...
45
  			$imageType = false;
03e52840d   Kload   Init
46
  		}
31b7f2792   Kload   Upgrade to ownclo...
47
  		return $imageType ? image_type_to_mime_type($imageType) : '';
03e52840d   Kload   Init
48
49
50
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
51
52
53
54
55
  	 * Constructor.
  	 * @param resource|string $imageRef The path to a local file, a base64 encoded string or a resource created by
  	 * an imagecreate* function.
  	 * @return \OC_Image False on error
  	 */
31b7f2792   Kload   Upgrade to ownclo...
56
  	public function __construct($imageRef = null) {
03e52840d   Kload   Init
57
58
59
60
61
  		//OC_Log::write('core',__METHOD__.'(): start', OC_Log::DEBUG);
  		if(!extension_loaded('gd') || !function_exists('gd_info')) {
  			OC_Log::write('core', __METHOD__.'(): GD module not installed', OC_Log::ERROR);
  			return false;
  		}
31b7f2792   Kload   Upgrade to ownclo...
62
63
64
65
66
67
68
  
  		if (\OC_Util::fileInfoLoaded()) {
  			$this->fileInfo = new finfo(FILEINFO_MIME_TYPE);
  		}
  
  		if(!is_null($imageRef)) {
  			$this->load($imageRef);
03e52840d   Kload   Init
69
70
71
72
  		}
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
73
74
  	* Determine whether the object contains an image resource.
  	* @return bool
03e52840d   Kload   Init
75
76
77
78
79
80
  	*/
  	public function valid() { // apparently you can't name a method 'empty'...
  		return is_resource($this->resource);
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
81
82
  	* Returns the MIME type of the image or an empty string if no image is loaded.
  	* @return string
03e52840d   Kload   Init
83
84
  	*/
  	public function mimeType() {
31b7f2792   Kload   Upgrade to ownclo...
85
  		return $this->valid() ? $this->mimeType : '';
03e52840d   Kload   Init
86
87
88
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
89
90
  	* Returns the width of the image or -1 if no image is loaded.
  	* @return int
03e52840d   Kload   Init
91
92
93
94
95
96
  	*/
  	public function width() {
  		return $this->valid() ? imagesx($this->resource) : -1;
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
97
98
  	* Returns the height of the image or -1 if no image is loaded.
  	* @return int
03e52840d   Kload   Init
99
100
101
102
103
104
  	*/
  	public function height() {
  		return $this->valid() ? imagesy($this->resource) : -1;
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
105
106
  	* Returns the width when the image orientation is top-left.
  	* @return int
03e52840d   Kload   Init
107
108
109
110
111
112
113
114
115
116
117
  	*/
  	public function widthTopLeft() {
  		$o = $this->getOrientation();
  		OC_Log::write('core', 'OC_Image->widthTopLeft() Orientation: '.$o, OC_Log::DEBUG);
  		switch($o) {
  			case -1:
  			case 1:
  			case 2: // Not tested
  			case 3:
  			case 4: // Not tested
  				return $this->width();
03e52840d   Kload   Init
118
119
120
121
122
  			case 5: // Not tested
  			case 6:
  			case 7: // Not tested
  			case 8:
  				return $this->height();
03e52840d   Kload   Init
123
124
125
126
127
  		}
  		return $this->width();
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
128
129
  	* Returns the height when the image orientation is top-left.
  	* @return int
03e52840d   Kload   Init
130
131
132
133
134
135
136
137
138
139
140
  	*/
  	public function heightTopLeft() {
  		$o = $this->getOrientation();
  		OC_Log::write('core', 'OC_Image->heightTopLeft() Orientation: '.$o, OC_Log::DEBUG);
  		switch($o) {
  			case -1:
  			case 1:
  			case 2: // Not tested
  			case 3:
  			case 4: // Not tested
  				return $this->height();
03e52840d   Kload   Init
141
142
143
144
145
  			case 5: // Not tested
  			case 6:
  			case 7: // Not tested
  			case 8:
  				return $this->width();
03e52840d   Kload   Init
146
147
148
149
150
  		}
  		return $this->height();
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
151
152
153
154
155
156
157
158
159
160
  	 * Outputs the image.
  	 * @param string $mimeType
  	 * @return bool
  	 */
  	public function show($mimeType=null) {
  		if($mimeType === null) {
  			$mimeType = $this->mimeType();
  		}
  		header('Content-Type: '.$mimeType);
  		return $this->_output(null, $mimeType);
03e52840d   Kload   Init
161
162
163
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
164
165
166
167
168
  	 * Saves the image.
  	 * @param string $filePath
  	 * @param string $mimeType
  	 * @return bool
  	 */
03e52840d   Kload   Init
169

6d9380f96   Cédric Dupont   Update sources OC...
170
171
172
173
  	public function save($filePath=null, $mimeType=null) {
  		if($mimeType === null) {
  			$mimeType = $this->mimeType();
  		}
31b7f2792   Kload   Upgrade to ownclo...
174
  		if($filePath === null && $this->filePath === null) {
03e52840d   Kload   Init
175
176
  			OC_Log::write('core', __METHOD__.'(): called with no path.', OC_Log::ERROR);
  			return false;
31b7f2792   Kload   Upgrade to ownclo...
177
178
  		} elseif($filePath === null && $this->filePath !== null) {
  			$filePath = $this->filePath;
03e52840d   Kload   Init
179
  		}
6d9380f96   Cédric Dupont   Update sources OC...
180
  		return $this->_output($filePath, $mimeType);
03e52840d   Kload   Init
181
182
183
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
184
185
186
187
188
189
190
  	 * Outputs/saves the image.
  	 * @param string $filePath
  	 * @param string $mimeType
  	 * @return bool
  	 * @throws Exception
  	 */
  	private function _output($filePath=null, $mimeType=null) {
31b7f2792   Kload   Upgrade to ownclo...
191
192
193
194
  		if($filePath) {
  			if (!file_exists(dirname($filePath)))
  				mkdir(dirname($filePath), 0777, true);
  			if(!is_writable(dirname($filePath))) {
03e52840d   Kload   Init
195
  				OC_Log::write('core',
31b7f2792   Kload   Upgrade to ownclo...
196
  					__METHOD__.'(): Directory \''.dirname($filePath).'\' is not writable.',
03e52840d   Kload   Init
197
198
  					OC_Log::ERROR);
  				return false;
31b7f2792   Kload   Upgrade to ownclo...
199
200
  			} elseif(is_writable(dirname($filePath)) && file_exists($filePath) && !is_writable($filePath)) {
  				OC_Log::write('core', __METHOD__.'(): File \''.$filePath.'\' is not writable.', OC_Log::ERROR);
03e52840d   Kload   Init
201
202
203
204
205
206
  				return false;
  			}
  		}
  		if (!$this->valid()) {
  			return false;
  		}
6d9380f96   Cédric Dupont   Update sources OC...
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
  		$imageType = $this->imageType;
  		if($mimeType !== null) {
  			switch($mimeType) {
  				case 'image/gif':
  					$imageType = IMAGETYPE_GIF;
  					break;
  				case 'image/jpeg':
  					$imageType = IMAGETYPE_JPEG;
  					break;
  				case 'image/png':
  					$imageType = IMAGETYPE_PNG;
  					break;
  				case 'image/x-xbitmap':
  					$imageType = IMAGETYPE_XBM;
  					break;
  				case 'image/bmp':
  					$imageType = IMAGETYPE_BMP;
  					break;
  				default:
  					throw new Exception('\OC_Image::_output(): "' . $mimeType . '" is not supported when forcing a specific output format');
  			}
  		}
  
  		switch($imageType) {
03e52840d   Kload   Init
231
  			case IMAGETYPE_GIF:
31b7f2792   Kload   Upgrade to ownclo...
232
  				$retVal = imagegif($this->resource, $filePath);
03e52840d   Kload   Init
233
234
  				break;
  			case IMAGETYPE_JPEG:
31b7f2792   Kload   Upgrade to ownclo...
235
  				$retVal = imagejpeg($this->resource, $filePath);
03e52840d   Kload   Init
236
237
  				break;
  			case IMAGETYPE_PNG:
31b7f2792   Kload   Upgrade to ownclo...
238
  				$retVal = imagepng($this->resource, $filePath);
03e52840d   Kload   Init
239
240
  				break;
  			case IMAGETYPE_XBM:
6d9380f96   Cédric Dupont   Update sources OC...
241
242
243
244
245
  				if (function_exists('imagexbm')) {
  					$retVal = imagexbm($this->resource, $filePath);
  				} else {
  					throw new Exception('\OC_Image::_output(): imagexbm() is not supported.');
  				}
03e52840d   Kload   Init
246
247
  				break;
  			case IMAGETYPE_WBMP:
31b7f2792   Kload   Upgrade to ownclo...
248
  				$retVal = imagewbmp($this->resource, $filePath);
03e52840d   Kload   Init
249
250
  				break;
  			case IMAGETYPE_BMP:
31b7f2792   Kload   Upgrade to ownclo...
251
  				$retVal = imagebmp($this->resource, $filePath, $this->bitDepth);
03e52840d   Kload   Init
252
253
  				break;
  			default:
31b7f2792   Kload   Upgrade to ownclo...
254
  				$retVal = imagepng($this->resource, $filePath);
03e52840d   Kload   Init
255
  		}
31b7f2792   Kload   Upgrade to ownclo...
256
  		return $retVal;
03e52840d   Kload   Init
257
258
259
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
260
  	* Prints the image when called as $image().
03e52840d   Kload   Init
261
262
263
264
265
266
  	*/
  	public function __invoke() {
  		return $this->show();
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
267
  	* @return resource Returns the image resource in any.
03e52840d   Kload   Init
268
269
270
271
272
273
  	*/
  	public function resource() {
  		return $this->resource;
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
274
  	* @return string Returns the raw image data.
03e52840d   Kload   Init
275
276
277
  	*/
  	function data() {
  		ob_start();
31b7f2792   Kload   Upgrade to ownclo...
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
  		switch ($this->mimeType) {
  			case "image/png":
  				$res = imagepng($this->resource);
  				break;
  			case "image/jpeg":
  				$res = imagejpeg($this->resource);
  				break;
  			case "image/gif":
  				$res = imagegif($this->resource);
  				break;
  			default:
  				$res = imagepng($this->resource);
  				OC_Log::write('core', 'OC_Image->data. Couldn\'t guess mimetype, defaulting to png', OC_Log::INFO);
  				break;
  		}
03e52840d   Kload   Init
293
294
295
296
297
298
299
  		if (!$res) {
  			OC_Log::write('core', 'OC_Image->data. Error getting image data.', OC_Log::ERROR);
  		}
  		return ob_get_clean();
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
300
301
  	 * @return string - base64 encoded, which is suitable for embedding in a VCard.
  	 */
03e52840d   Kload   Init
302
303
304
305
306
307
  	function __toString() {
  		return base64_encode($this->data());
  	}
  
  	/**
  	* (I'm open for suggestions on better method name ;)
6d9380f96   Cédric Dupont   Update sources OC...
308
309
  	* Get the orientation based on EXIF data.
  	* @return int The orientation or -1 if no EXIF data is available.
03e52840d   Kload   Init
310
311
312
313
314
315
316
317
318
319
  	*/
  	public function getOrientation() {
  		if(!is_callable('exif_read_data')) {
  			OC_Log::write('core', 'OC_Image->fixOrientation() Exif module not enabled.', OC_Log::DEBUG);
  			return -1;
  		}
  		if(!$this->valid()) {
  			OC_Log::write('core', 'OC_Image->fixOrientation() No image loaded.', OC_Log::DEBUG);
  			return -1;
  		}
31b7f2792   Kload   Upgrade to ownclo...
320
  		if(is_null($this->filePath) || !is_readable($this->filePath)) {
03e52840d   Kload   Init
321
322
323
  			OC_Log::write('core', 'OC_Image->fixOrientation() No readable file path set.', OC_Log::DEBUG);
  			return -1;
  		}
31b7f2792   Kload   Upgrade to ownclo...
324
  		$exif = @exif_read_data($this->filePath, 'IFD0');
03e52840d   Kload   Init
325
326
327
328
329
330
331
332
333
334
335
  		if(!$exif) {
  			return -1;
  		}
  		if(!isset($exif['Orientation'])) {
  			return -1;
  		}
  		return $exif['Orientation'];
  	}
  
  	/**
  	* (I'm open for suggestions on better method name ;)
6d9380f96   Cédric Dupont   Update sources OC...
336
337
  	* Fixes orientation based on EXIF data.
  	* @return bool.
03e52840d   Kload   Init
338
339
340
341
342
  	*/
  	public function fixOrientation() {
  		$o = $this->getOrientation();
  		OC_Log::write('core', 'OC_Image->fixOrientation() Orientation: '.$o, OC_Log::DEBUG);
  		$rotate = 0;
03e52840d   Kload   Init
343
344
345
  		switch($o) {
  			case -1:
  				return false; //Nothing to fix
03e52840d   Kload   Init
346
347
  			case 1:
  				$rotate = 0;
03e52840d   Kload   Init
348
349
350
  				break;
  			case 2: // Not tested
  				$rotate = 0;
03e52840d   Kload   Init
351
352
353
  				break;
  			case 3:
  				$rotate = 180;
03e52840d   Kload   Init
354
355
356
  				break;
  			case 4: // Not tested
  				$rotate = 180;
03e52840d   Kload   Init
357
358
359
  				break;
  			case 5: // Not tested
  				$rotate = 90;
03e52840d   Kload   Init
360
361
362
363
  				break;
  			case 6:
  				//$rotate = 90;
  				$rotate = 270;
03e52840d   Kload   Init
364
365
366
  				break;
  			case 7: // Not tested
  				$rotate = 270;
03e52840d   Kload   Init
367
368
369
  				break;
  			case 8:
  				$rotate = 90;
03e52840d   Kload   Init
370
371
372
  				break;
  		}
  		if($rotate) {
6d9380f96   Cédric Dupont   Update sources OC...
373
  			$res = imagerotate($this->resource, $rotate, 0);
03e52840d   Kload   Init
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
  			if($res) {
  				if(imagealphablending($res, true)) {
  					if(imagesavealpha($res, true)) {
  						imagedestroy($this->resource);
  						$this->resource = $res;
  						return true;
  					} else {
  						OC_Log::write('core', 'OC_Image->fixOrientation() Error during alphasaving.', OC_Log::DEBUG);
  						return false;
  					}
  				} else {
  					OC_Log::write('core', 'OC_Image->fixOrientation() Error during alphablending.', OC_Log::DEBUG);
  					return false;
  				}
  			} else {
  				OC_Log::write('core', 'OC_Image->fixOrientation() Error during oriention fixing.', OC_Log::DEBUG);
  				return false;
  			}
  		}
6d9380f96   Cédric Dupont   Update sources OC...
393
  		return false;
03e52840d   Kload   Init
394
395
396
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
397
398
399
400
  	 * Loads an image from a local file, a base64 encoded string or a resource created by an imagecreate* function.
  	 * @param resource|string $imageRef The path to a local file, a base64 encoded string or a resource created by an imagecreate* function or a file resource (file handle    ).
  	 * @return resource|false An image resource or false on error
  	 */
31b7f2792   Kload   Upgrade to ownclo...
401
402
403
404
  	public function load($imageRef) {
  		if(is_resource($imageRef)) {
  			if(get_resource_type($imageRef) == 'gd') {
  				$this->resource = $imageRef;
03e52840d   Kload   Init
405
  				return $this->resource;
31b7f2792   Kload   Upgrade to ownclo...
406
407
  			} elseif(in_array(get_resource_type($imageRef), array('file', 'stream'))) {
  				return $this->loadFromFileHandle($imageRef);
03e52840d   Kload   Init
408
  			}
31b7f2792   Kload   Upgrade to ownclo...
409
  		} elseif($this->loadFromBase64($imageRef) !== false) {
03e52840d   Kload   Init
410
  			return $this->resource;
6d9380f96   Cédric Dupont   Update sources OC...
411
412
  		} elseif($this->loadFromFile($imageRef) !== false) {
  			return $this->resource;
31b7f2792   Kload   Upgrade to ownclo...
413
  		} elseif($this->loadFromData($imageRef) !== false) {
03e52840d   Kload   Init
414
415
416
417
418
419
420
421
  			return $this->resource;
  		} else {
  			OC_Log::write('core', __METHOD__.'(): couldn\'t load anything. Giving up!', OC_Log::DEBUG);
  			return false;
  		}
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
422
  	* Loads an image from an open file handle.
03e52840d   Kload   Init
423
  	* It is the responsibility of the caller to position the pointer at the correct place and to close the handle again.
6d9380f96   Cédric Dupont   Update sources OC...
424
425
  	* @param resource $handle
  	* @return resource|false An image resource or false on error
03e52840d   Kload   Init
426
427
428
429
430
431
432
433
434
435
  	*/
  	public function loadFromFileHandle($handle) {
  		OC_Log::write('core', __METHOD__.'(): Trying', OC_Log::DEBUG);
  		$contents = stream_get_contents($handle);
  		if($this->loadFromData($contents)) {
  			return $this->resource;
  		}
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
436
437
438
  	* Loads an image from a local file.
  	* @param bool|string $imagePath The path to a local file.
  	* @return bool|resource An image resource or false on error
03e52840d   Kload   Init
439
  	*/
31b7f2792   Kload   Upgrade to ownclo...
440
  	public function loadFromFile($imagePath=false) {
03e52840d   Kload   Init
441
  		// exif_imagetype throws "read error!" if file is less than 12 byte
31b7f2792   Kload   Upgrade to ownclo...
442
  		if(!@is_file($imagePath) || !file_exists($imagePath) || filesize($imagePath) < 12 || !is_readable($imagePath)) {
6d9380f96   Cédric Dupont   Update sources OC...
443
  			OC_Log::write('core', 'OC_Image->loadFromFile, couldn\'t load: ' . (string) urlencode($imagePath), OC_Log::DEBUG);
03e52840d   Kload   Init
444
445
  			return false;
  		}
31b7f2792   Kload   Upgrade to ownclo...
446
447
  		$iType = exif_imagetype($imagePath);
  		switch ($iType) {
03e52840d   Kload   Init
448
449
  			case IMAGETYPE_GIF:
  				if (imagetypes() & IMG_GIF) {
31b7f2792   Kload   Upgrade to ownclo...
450
  					$this->resource = imagecreatefromgif($imagePath);
03e52840d   Kload   Init
451
452
  				} else {
  					OC_Log::write('core',
31b7f2792   Kload   Upgrade to ownclo...
453
  						'OC_Image->loadFromFile, GIF images not supported: '.$imagePath,
03e52840d   Kload   Init
454
455
456
457
458
  						OC_Log::DEBUG);
  				}
  				break;
  			case IMAGETYPE_JPEG:
  				if (imagetypes() & IMG_JPG) {
31b7f2792   Kload   Upgrade to ownclo...
459
  					$this->resource = imagecreatefromjpeg($imagePath);
03e52840d   Kload   Init
460
461
  				} else {
  					OC_Log::write('core',
31b7f2792   Kload   Upgrade to ownclo...
462
  						'OC_Image->loadFromFile, JPG images not supported: '.$imagePath,
03e52840d   Kload   Init
463
464
465
466
467
  						OC_Log::DEBUG);
  				}
  				break;
  			case IMAGETYPE_PNG:
  				if (imagetypes() & IMG_PNG) {
31b7f2792   Kload   Upgrade to ownclo...
468
  					$this->resource = imagecreatefrompng($imagePath);
03e52840d   Kload   Init
469
470
  				} else {
  					OC_Log::write('core',
31b7f2792   Kload   Upgrade to ownclo...
471
  						'OC_Image->loadFromFile, PNG images not supported: '.$imagePath,
03e52840d   Kload   Init
472
473
474
475
476
  						OC_Log::DEBUG);
  				}
  				break;
  			case IMAGETYPE_XBM:
  				if (imagetypes() & IMG_XPM) {
31b7f2792   Kload   Upgrade to ownclo...
477
  					$this->resource = imagecreatefromxbm($imagePath);
03e52840d   Kload   Init
478
479
  				} else {
  					OC_Log::write('core',
31b7f2792   Kload   Upgrade to ownclo...
480
  						'OC_Image->loadFromFile, XBM/XPM images not supported: '.$imagePath,
03e52840d   Kload   Init
481
482
483
484
485
  						OC_Log::DEBUG);
  				}
  				break;
  			case IMAGETYPE_WBMP:
  				if (imagetypes() & IMG_WBMP) {
31b7f2792   Kload   Upgrade to ownclo...
486
  					$this->resource = imagecreatefromwbmp($imagePath);
03e52840d   Kload   Init
487
488
  				} else {
  					OC_Log::write('core',
31b7f2792   Kload   Upgrade to ownclo...
489
  						'OC_Image->loadFromFile, WBMP images not supported: '.$imagePath,
03e52840d   Kload   Init
490
491
492
493
  						OC_Log::DEBUG);
  				}
  				break;
  			case IMAGETYPE_BMP:
31b7f2792   Kload   Upgrade to ownclo...
494
  					$this->resource = $this->imagecreatefrombmp($imagePath);
03e52840d   Kload   Init
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
  				break;
  			/*
  			case IMAGETYPE_TIFF_II: // (intel byte order)
  				break;
  			case IMAGETYPE_TIFF_MM: // (motorola byte order)
  				break;
  			case IMAGETYPE_JPC:
  				break;
  			case IMAGETYPE_JP2:
  				break;
  			case IMAGETYPE_JPX:
  				break;
  			case IMAGETYPE_JB2:
  				break;
  			case IMAGETYPE_SWC:
  				break;
  			case IMAGETYPE_IFF:
  				break;
  			case IMAGETYPE_ICO:
  				break;
  			case IMAGETYPE_SWF:
  				break;
  			case IMAGETYPE_PSD:
  				break;
  			*/
  			default:
  
  				// this is mostly file created from encrypted file
31b7f2792   Kload   Upgrade to ownclo...
523
524
  				$this->resource = imagecreatefromstring(\OC\Files\Filesystem::file_get_contents(\OC\Files\Filesystem::getLocalPath($imagePath)));
  				$iType = IMAGETYPE_PNG;
03e52840d   Kload   Init
525
526
527
528
  				OC_Log::write('core', 'OC_Image->loadFromFile, Default', OC_Log::DEBUG);
  				break;
  		}
  		if($this->valid()) {
31b7f2792   Kload   Upgrade to ownclo...
529
530
531
  			$this->imageType = $iType;
  			$this->mimeType = image_type_to_mime_type($iType);
  			$this->filePath = $imagePath;
03e52840d   Kload   Init
532
533
534
535
536
  		}
  		return $this->resource;
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
537
538
539
  	* Loads an image from a string of data.
  	* @param string $str A string of image data as read from a file.
  	* @return bool|resource An image resource or false on error
03e52840d   Kload   Init
540
541
542
543
544
545
  	*/
  	public function loadFromData($str) {
  		if(is_resource($str)) {
  			return false;
  		}
  		$this->resource = @imagecreatefromstring($str);
31b7f2792   Kload   Upgrade to ownclo...
546
547
548
549
550
551
552
  		if ($this->fileInfo) {
  			$this->mimeType = $this->fileInfo->buffer($str);
  		}
  		if(is_resource($this->resource)) {
  			imagealphablending($this->resource, false);
  			imagesavealpha($this->resource, true);
  		}
03e52840d   Kload   Init
553
554
555
556
557
558
559
560
  		if(!$this->resource) {
  			OC_Log::write('core', 'OC_Image->loadFromData, couldn\'t load', OC_Log::DEBUG);
  			return false;
  		}
  		return $this->resource;
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
561
562
563
  	* Loads an image from a base64 encoded string.
  	* @param string $str A string base64 encoded string of image data.
  	* @return bool|resource An image resource or false on error
03e52840d   Kload   Init
564
565
566
567
568
569
570
571
  	*/
  	public function loadFromBase64($str) {
  		if(!is_string($str)) {
  			return false;
  		}
  		$data = base64_decode($str);
  		if($data) { // try to load from string data
  			$this->resource = @imagecreatefromstring($data);
31b7f2792   Kload   Upgrade to ownclo...
572
573
574
  			if ($this->fileInfo) {
  				$this->mimeType = $this->fileInfo->buffer($data);
  			}
03e52840d   Kload   Init
575
576
577
578
579
580
581
582
583
584
585
586
587
588
  			if(!$this->resource) {
  				OC_Log::write('core', 'OC_Image->loadFromBase64, couldn\'t load', OC_Log::DEBUG);
  				return false;
  			}
  			return $this->resource;
  		} else {
  			return false;
  		}
  	}
  
  	/**
  	 * Create a new image from file or URL
  	 * @link http://www.programmierer-forum.de/function-imagecreatefrombmp-laeuft-mit-allen-bitraten-t143137.htm
  	 * @version 1.00
6d9380f96   Cédric Dupont   Update sources OC...
589
  	 * @param string $fileName <p>
03e52840d   Kload   Init
590
591
  	 * Path to the BMP image.
  	 * </p>
6d9380f96   Cédric Dupont   Update sources OC...
592
  	 * @return bool|resource an image resource identifier on success, <b>FALSE</b> on errors.
03e52840d   Kload   Init
593
  	 */
31b7f2792   Kload   Upgrade to ownclo...
594
595
596
  	private function imagecreatefrombmp($fileName) {
  		if (!($fh = fopen($fileName, 'rb'))) {
  			trigger_error('imagecreatefrombmp: Can not open ' . $fileName, E_USER_WARNING);
03e52840d   Kload   Init
597
598
599
600
601
602
  			return false;
  		}
  		// read file header
  		$meta = unpack('vtype/Vfilesize/Vreserved/Voffset', fread($fh, 14));
  		// check for bitmap
  		if ($meta['type'] != 19778) {
31b7f2792   Kload   Upgrade to ownclo...
603
  			trigger_error('imagecreatefrombmp: ' . $fileName . ' is not a bitmap!', E_USER_WARNING);
03e52840d   Kload   Init
604
605
606
607
608
609
610
611
612
613
  			return false;
  		}
  		// read image header
  		$meta += unpack('Vheadersize/Vwidth/Vheight/vplanes/vbits/Vcompression/Vimagesize/Vxres/Vyres/Vcolors/Vimportant', fread($fh, 40));
  		// read additional 16bit header
  		if ($meta['bits'] == 16) {
  			$meta += unpack('VrMask/VgMask/VbMask', fread($fh, 12));
  		}
  		// set bytes and padding
  		$meta['bytes'] = $meta['bits'] / 8;
31b7f2792   Kload   Upgrade to ownclo...
614
  		$this->bitDepth = $meta['bits']; //remember the bit depth for the imagebmp call
03e52840d   Kload   Init
615
616
617
618
619
620
621
622
623
  		$meta['decal'] = 4 - (4 * (($meta['width'] * $meta['bytes'] / 4)- floor($meta['width'] * $meta['bytes'] / 4)));
  		if ($meta['decal'] == 4) {
  			$meta['decal'] = 0;
  		}
  		// obtain imagesize
  		if ($meta['imagesize'] < 1) {
  			$meta['imagesize'] = $meta['filesize'] - $meta['offset'];
  			// in rare cases filesize is equal to offset so we need to read physical size
  			if ($meta['imagesize'] < 1) {
6d9380f96   Cédric Dupont   Update sources OC...
624
  				$meta['imagesize'] = @filesize($fileName) - $meta['offset'];
03e52840d   Kload   Init
625
  				if ($meta['imagesize'] < 1) {
6d9380f96   Cédric Dupont   Update sources OC...
626
  					trigger_error('imagecreatefrombmp: Can not obtain filesize of ' . $fileName . '!', E_USER_WARNING);
03e52840d   Kload   Init
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
  					return false;
  				}
  			}
  		}
  		// calculate colors
  		$meta['colors'] = !$meta['colors'] ? pow(2, $meta['bits']) : $meta['colors'];
  		// read color palette
  		$palette = array();
  		if ($meta['bits'] < 16) {
  			$palette = unpack('l' . $meta['colors'], fread($fh, $meta['colors'] * 4));
  			// in rare cases the color value is signed
  			if ($palette[1] < 0) {
  				foreach ($palette as $i => $color) {
  					$palette[$i] = $color + 16777216;
  				}
  			}
  		}
  		// create gd image
  		$im = imagecreatetruecolor($meta['width'], $meta['height']);
  		$data = fread($fh, $meta['imagesize']);
  		$p = 0;
  		$vide = chr(0);
  		$y = $meta['height'] - 1;
31b7f2792   Kload   Upgrade to ownclo...
650
  		$error = 'imagecreatefrombmp: ' . $fileName . ' has not enough data!';
03e52840d   Kload   Init
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
  		// loop through the image data beginning with the lower left corner
  		while ($y >= 0) {
  			$x = 0;
  			while ($x < $meta['width']) {
  				switch ($meta['bits']) {
  					case 32:
  					case 24:
  						if (!($part = substr($data, $p, 3))) {
  							trigger_error($error, E_USER_WARNING);
  							return $im;
  						}
  						$color = unpack('V', $part . $vide);
  						break;
  					case 16:
  						if (!($part = substr($data, $p, 2))) {
  							trigger_error($error, E_USER_WARNING);
  							return $im;
  						}
  						$color = unpack('v', $part);
  						$color[1] = (($color[1] & 0xf800) >> 8) * 65536 + (($color[1] & 0x07e0) >> 3) * 256 + (($color[1] & 0x001f) << 3);
  						break;
  					case 8:
  						$color = unpack('n', $vide . substr($data, $p, 1));
  						$color[1] = $palette[ $color[1] + 1 ];
  						break;
  					case 4:
  						$color = unpack('n', $vide . substr($data, floor($p), 1));
  						$color[1] = ($p * 2) % 2 == 0 ? $color[1] >> 4 : $color[1] & 0x0F;
  						$color[1] = $palette[ $color[1] + 1 ];
  						break;
  					case 1:
  						$color = unpack('n', $vide . substr($data, floor($p), 1));
  						switch (($p * 8) % 8) {
  							case 0:
  								$color[1] = $color[1] >> 7;
  								break;
  							case 1:
  								$color[1] = ($color[1] & 0x40) >> 6;
  								break;
  							case 2:
  								$color[1] = ($color[1] & 0x20) >> 5;
  								break;
  							case 3:
  								$color[1] = ($color[1] & 0x10) >> 4;
  								break;
  							case 4:
  								$color[1] = ($color[1] & 0x8) >> 3;
  								break;
  							case 5:
  								$color[1] = ($color[1] & 0x4) >> 2;
  								break;
  							case 6:
  								$color[1] = ($color[1] & 0x2) >> 1;
  								break;
  							case 7:
  								$color[1] = ($color[1] & 0x1);
  								break;
  						}
  						$color[1] = $palette[ $color[1] + 1 ];
  						break;
  					default:
  						trigger_error('imagecreatefrombmp: '
31b7f2792   Kload   Upgrade to ownclo...
713
  							. $fileName . ' has ' . $meta['bits'] . ' bits and this is not supported!',
03e52840d   Kload   Init
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
  							E_USER_WARNING);
  						return false;
  				}
  				imagesetpixel($im, $x, $y, $color[1]);
  				$x++;
  				$p += $meta['bytes'];
  			}
  			$y--;
  			$p += $meta['decal'];
  		}
  		fclose($fh);
  		return $im;
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
729
730
731
  	* Resizes the image preserving ratio.
  	* @param integer $maxSize The maximum size of either the width or height.
  	* @return bool
03e52840d   Kload   Init
732
  	*/
31b7f2792   Kload   Upgrade to ownclo...
733
  	public function resize($maxSize) {
03e52840d   Kload   Init
734
735
736
737
  		if(!$this->valid()) {
  			OC_Log::write('core', __METHOD__.'(): No image loaded', OC_Log::ERROR);
  			return false;
  		}
31b7f2792   Kload   Upgrade to ownclo...
738
739
740
  		$widthOrig=imageSX($this->resource);
  		$heightOrig=imageSY($this->resource);
  		$ratioOrig = $widthOrig/$heightOrig;
03e52840d   Kload   Init
741

31b7f2792   Kload   Upgrade to ownclo...
742
743
744
  		if ($ratioOrig > 1) {
  			$newHeight = round($maxSize/$ratioOrig);
  			$newWidth = $maxSize;
03e52840d   Kload   Init
745
  		} else {
31b7f2792   Kload   Upgrade to ownclo...
746
747
  			$newWidth = round($maxSize*$ratioOrig);
  			$newHeight = $maxSize;
03e52840d   Kload   Init
748
  		}
31b7f2792   Kload   Upgrade to ownclo...
749
  		$this->preciseResize(round($newWidth), round($newHeight));
03e52840d   Kload   Init
750
751
  		return true;
  	}
6d9380f96   Cédric Dupont   Update sources OC...
752
753
754
755
756
  	/**
  	 * @param int $width
  	 * @param int $height
  	 * @return bool
  	 */
03e52840d   Kload   Init
757
758
759
760
761
  	public function preciseResize($width, $height) {
  		if (!$this->valid()) {
  			OC_Log::write('core', __METHOD__.'(): No image loaded', OC_Log::ERROR);
  			return false;
  		}
31b7f2792   Kload   Upgrade to ownclo...
762
763
  		$widthOrig=imageSX($this->resource);
  		$heightOrig=imageSY($this->resource);
03e52840d   Kload   Init
764
765
766
767
768
769
770
771
772
  		$process = imagecreatetruecolor($width, $height);
  
  		if ($process == false) {
  			OC_Log::write('core', __METHOD__.'(): Error creating true color image', OC_Log::ERROR);
  			imagedestroy($process);
  			return false;
  		}
  
  		// preserve transparency
31b7f2792   Kload   Upgrade to ownclo...
773
  		if($this->imageType == IMAGETYPE_GIF or $this->imageType == IMAGETYPE_PNG) {
03e52840d   Kload   Init
774
775
776
777
  			imagecolortransparent($process, imagecolorallocatealpha($process, 0, 0, 0, 127));
  			imagealphablending($process, false);
  			imagesavealpha($process, true);
  		}
31b7f2792   Kload   Upgrade to ownclo...
778
  		imagecopyresampled($process, $this->resource, 0, 0, 0, 0, $width, $height, $widthOrig, $heightOrig);
03e52840d   Kload   Init
779
780
781
782
783
784
785
786
787
788
789
  		if ($process == false) {
  			OC_Log::write('core', __METHOD__.'(): Error resampling process image '.$width.'x'.$height, OC_Log::ERROR);
  			imagedestroy($process);
  			return false;
  		}
  		imagedestroy($this->resource);
  		$this->resource = $process;
  		return true;
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
790
791
792
  	* Crops the image to the middle square. If the image is already square it just returns.
  	* @param int $size maximum size for the result (optional)
  	* @return bool for success or failure
03e52840d   Kload   Init
793
794
795
796
797
798
  	*/
  	public function centerCrop($size=0) {
  		if(!$this->valid()) {
  			OC_Log::write('core', 'OC_Image->centerCrop, No image loaded', OC_Log::ERROR);
  			return false;
  		}
31b7f2792   Kload   Upgrade to ownclo...
799
800
801
  		$widthOrig=imageSX($this->resource);
  		$heightOrig=imageSY($this->resource);
  		if($widthOrig === $heightOrig and $size==0) {
03e52840d   Kload   Init
802
803
  			return true;
  		}
31b7f2792   Kload   Upgrade to ownclo...
804
805
  		$ratioOrig = $widthOrig/$heightOrig;
  		$width = $height = min($widthOrig, $heightOrig);
03e52840d   Kload   Init
806

31b7f2792   Kload   Upgrade to ownclo...
807
808
  		if ($ratioOrig > 1) {
  			$x = ($widthOrig/2) - ($width/2);
03e52840d   Kload   Init
809
810
  			$y = 0;
  		} else {
31b7f2792   Kload   Upgrade to ownclo...
811
  			$y = ($heightOrig/2) - ($height/2);
03e52840d   Kload   Init
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
  			$x = 0;
  		}
  		if($size>0) {
  			$targetWidth=$size;
  			$targetHeight=$size;
  		}else{
  			$targetWidth=$width;
  			$targetHeight=$height;
  		}
  		$process = imagecreatetruecolor($targetWidth, $targetHeight);
  		if ($process == false) {
  			OC_Log::write('core', 'OC_Image->centerCrop. Error creating true color image', OC_Log::ERROR);
  			imagedestroy($process);
  			return false;
  		}
  
  		// preserve transparency
31b7f2792   Kload   Upgrade to ownclo...
829
  		if($this->imageType == IMAGETYPE_GIF or $this->imageType == IMAGETYPE_PNG) {
03e52840d   Kload   Init
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
  			imagecolortransparent($process, imagecolorallocatealpha($process, 0, 0, 0, 127));
  			imagealphablending($process, false);
  			imagesavealpha($process, true);
  		}
  
  		imagecopyresampled($process, $this->resource, 0, 0, $x, $y, $targetWidth, $targetHeight, $width, $height);
  		if ($process == false) {
  			OC_Log::write('core',
  				'OC_Image->centerCrop. Error resampling process image '.$width.'x'.$height,
  				OC_Log::ERROR);
  			imagedestroy($process);
  			return false;
  		}
  		imagedestroy($this->resource);
  		$this->resource = $process;
  		return true;
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
849
850
851
852
853
854
  	* Crops the image from point $x$y with dimension $wx$h.
  	* @param int $x Horizontal position
  	* @param int $y Vertical position
  	* @param int $w Width
  	* @param int $h Height
  	* @return bool for success or failure
03e52840d   Kload   Init
855
856
857
858
859
860
861
862
863
864
865
866
  	*/
  	public function crop($x, $y, $w, $h) {
  		if(!$this->valid()) {
  			OC_Log::write('core', __METHOD__.'(): No image loaded', OC_Log::ERROR);
  			return false;
  		}
  		$process = imagecreatetruecolor($w, $h);
  		if ($process == false) {
  			OC_Log::write('core', __METHOD__.'(): Error creating true color image', OC_Log::ERROR);
  			imagedestroy($process);
  			return false;
  		}
6d9380f96   Cédric Dupont   Update sources OC...
867
868
869
870
871
872
873
  
  		// preserve transparency
  		if($this->imageType == IMAGETYPE_GIF or $this->imageType == IMAGETYPE_PNG) {
  			imagecolortransparent($process, imagecolorallocatealpha($process, 0, 0, 0, 127));
  			imagealphablending($process, false);
  			imagesavealpha($process, true);
  		}
03e52840d   Kload   Init
874
875
876
877
878
879
880
881
882
883
884
885
  		imagecopyresampled($process, $this->resource, 0, 0, $x, $y, $w, $h, $w, $h);
  		if ($process == false) {
  			OC_Log::write('core', __METHOD__.'(): Error resampling process image '.$w.'x'.$h, OC_Log::ERROR);
  			imagedestroy($process);
  			return false;
  		}
  		imagedestroy($this->resource);
  		$this->resource = $process;
  		return true;
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
886
887
888
889
  	 * Resizes the image to fit within a boundry while preserving ratio.
  	 * @param integer $maxWidth
  	 * @param integer $maxHeight
  	 * @return bool
03e52840d   Kload   Init
890
891
892
893
894
895
  	 */
  	public function fitIn($maxWidth, $maxHeight) {
  		if(!$this->valid()) {
  			OC_Log::write('core', __METHOD__.'(): No image loaded', OC_Log::ERROR);
  			return false;
  		}
31b7f2792   Kload   Upgrade to ownclo...
896
897
898
  		$widthOrig=imageSX($this->resource);
  		$heightOrig=imageSY($this->resource);
  		$ratio = $widthOrig/$heightOrig;
03e52840d   Kload   Init
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
  
  		$newWidth = min($maxWidth, $ratio*$maxHeight);
  		$newHeight = min($maxHeight, $maxWidth/$ratio);
  
  		$this->preciseResize(round($newWidth), round($newHeight));
  		return true;
  	}
  
  	public function destroy() {
  		if($this->valid()) {
  			imagedestroy($this->resource);
  		}
  		$this->resource=null;
  	}
  
  	public function __destruct() {
  		$this->destroy();
  	}
  }
  if ( ! function_exists( 'imagebmp') ) {
  	/**
  	 * Output a BMP image to either the browser or a file
  	 * @link http://www.ugia.cn/wp-data/imagebmp.php
  	 * @author legend <legendsky@hotmail.com>
  	 * @link http://www.programmierer-forum.de/imagebmp-gute-funktion-gefunden-t143716.htm
  	 * @author mgutt <marc@gutt.it>
  	 * @version 1.00
6d9380f96   Cédric Dupont   Update sources OC...
926
  	 * @param string $fileName [optional] <p>The path to save the file to.</p>
03e52840d   Kload   Init
927
928
929
930
  	 * @param int $bit [optional] <p>Bit depth, (default is 24).</p>
  	 * @param int $compression [optional]
  	 * @return bool <b>TRUE</b> on success or <b>FALSE</b> on failure.
  	 */
31b7f2792   Kload   Upgrade to ownclo...
931
  	function imagebmp($im, $fileName='', $bit=24, $compression=0) {
03e52840d   Kload   Init
932
933
934
935
936
937
938
939
940
941
  		if (!in_array($bit, array(1, 4, 8, 16, 24, 32))) {
  			$bit = 24;
  		}
  		else if ($bit == 32) {
  			$bit = 24;
  		}
  		$bits = pow(2, $bit);
  		imagetruecolortopalette($im, true, $bits);
  		$width = imagesx($im);
  		$height = imagesy($im);
31b7f2792   Kload   Upgrade to ownclo...
942
943
  		$colorsNum = imagecolorstotal($im);
  		$rgbQuad = '';
03e52840d   Kload   Init
944
  		if ($bit <= 8) {
31b7f2792   Kload   Upgrade to ownclo...
945
  			for ($i = 0; $i < $colorsNum; $i++) {
03e52840d   Kload   Init
946
  				$colors = imagecolorsforindex($im, $i);
31b7f2792   Kload   Upgrade to ownclo...
947
  				$rgbQuad .= chr($colors['blue']) . chr($colors['green']) . chr($colors['red']) . "\0";
03e52840d   Kload   Init
948
  			}
31b7f2792   Kload   Upgrade to ownclo...
949
  			$bmpData = '';
03e52840d   Kload   Init
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
  			if ($compression == 0 || $bit < 8) {
  				$compression = 0;
  				$extra = '';
  				$padding = 4 - ceil($width / (8 / $bit)) % 4;
  				if ($padding % 4 != 0) {
  					$extra = str_repeat("\0", $padding);
  				}
  				for ($j = $height - 1; $j >= 0; $j --) {
  					$i = 0;
  					while ($i < $width) {
  						$bin = 0;
  						$limit = $width - $i < 8 / $bit ? (8 / $bit - $width + $i) * $bit : 0;
  						for ($k = 8 - $bit; $k >= $limit; $k -= $bit) {
  							$index = imagecolorat($im, $i, $j);
  							$bin |= $index << $k;
  							$i++;
  						}
31b7f2792   Kload   Upgrade to ownclo...
967
  						$bmpData .= chr($bin);
03e52840d   Kload   Init
968
  					}
31b7f2792   Kload   Upgrade to ownclo...
969
  					$bmpData .= $extra;
03e52840d   Kload   Init
970
971
972
973
974
  				}
  			}
  			// RLE8
  			else if ($compression == 1 && $bit == 8) {
  				for ($j = $height - 1; $j >= 0; $j--) {
31b7f2792   Kload   Upgrade to ownclo...
975
976
  					$lastIndex = "\0";
  					$sameNum = 0;
03e52840d   Kload   Init
977
978
  					for ($i = 0; $i <= $width; $i++) {
  						$index = imagecolorat($im, $i, $j);
31b7f2792   Kload   Upgrade to ownclo...
979
980
  						if ($index !== $lastIndex || $sameNum > 255) {
  							if ($sameNum != 0) {
6d9380f96   Cédric Dupont   Update sources OC...
981
  								$bmpData .= chr($sameNum) . chr($lastIndex);
03e52840d   Kload   Init
982
  							}
31b7f2792   Kload   Upgrade to ownclo...
983
984
  							$lastIndex = $index;
  							$sameNum = 1;
03e52840d   Kload   Init
985
986
  						}
  						else {
31b7f2792   Kload   Upgrade to ownclo...
987
  							$sameNum++;
03e52840d   Kload   Init
988
989
  						}
  					}
31b7f2792   Kload   Upgrade to ownclo...
990
  					$bmpData .= "\0\0";
03e52840d   Kload   Init
991
  				}
31b7f2792   Kload   Upgrade to ownclo...
992
  				$bmpData .= "\0\1";
03e52840d   Kload   Init
993
  			}
31b7f2792   Kload   Upgrade to ownclo...
994
995
  			$sizeQuad = strlen($rgbQuad);
  			$sizeData = strlen($bmpData);
03e52840d   Kload   Init
996
997
998
999
1000
1001
1002
  		}
  		else {
  			$extra = '';
  			$padding = 4 - ($width * ($bit / 8)) % 4;
  			if ($padding % 4 != 0) {
  				$extra = str_repeat("\0", $padding);
  			}
31b7f2792   Kload   Upgrade to ownclo...
1003
  			$bmpData = '';
03e52840d   Kload   Init
1004
1005
1006
1007
1008
1009
1010
1011
1012
  			for ($j = $height - 1; $j >= 0; $j--) {
  				for ($i = 0; $i < $width; $i++) {
  					$index  = imagecolorat($im, $i, $j);
  					$colors = imagecolorsforindex($im, $index);
  					if ($bit == 16) {
  						$bin = 0 << $bit;
  						$bin |= ($colors['red'] >> 3) << 10;
  						$bin |= ($colors['green'] >> 3) << 5;
  						$bin |= $colors['blue'] >> 3;
31b7f2792   Kload   Upgrade to ownclo...
1013
  						$bmpData .= pack("v", $bin);
03e52840d   Kload   Init
1014
1015
  					}
  					else {
31b7f2792   Kload   Upgrade to ownclo...
1016
  						$bmpData .= pack("c*", $colors['blue'], $colors['green'], $colors['red']);
03e52840d   Kload   Init
1017
1018
  					}
  				}
31b7f2792   Kload   Upgrade to ownclo...
1019
  				$bmpData .= $extra;
03e52840d   Kload   Init
1020
  			}
31b7f2792   Kload   Upgrade to ownclo...
1021
1022
1023
1024
1025
1026
1027
1028
1029
  			$sizeQuad = 0;
  			$sizeData = strlen($bmpData);
  			$colorsNum = 0;
  		}
  		$fileHeader = 'BM' . pack('V3', 54 + $sizeQuad + $sizeData, 0, 54 + $sizeQuad);
  		$infoHeader = pack('V3v2V*', 0x28, $width, $height, 1, $bit, $compression, $sizeData, 0, 0, $colorsNum, 0);
  		if ($fileName != '') {
  			$fp = fopen($fileName, 'wb');
  			fwrite($fp, $fileHeader . $infoHeader . $rgbQuad . $bmpData);
03e52840d   Kload   Init
1030
1031
1032
  			fclose($fp);
  			return true;
  		}
31b7f2792   Kload   Upgrade to ownclo...
1033
  		echo $fileHeader . $infoHeader. $rgbQuad . $bmpData;
03e52840d   Kload   Init
1034
1035
1036
1037
1038
1039
1040
1041
  		return true;
  	}
  }
  
  if ( ! function_exists( 'exif_imagetype' ) ) {
  	/**
  	 * Workaround if exif_imagetype does not exist
  	 * @link http://www.php.net/manual/en/function.exif-imagetype.php#80383
6d9380f96   Cédric Dupont   Update sources OC...
1042
  	 * @param string $fileName
03e52840d   Kload   Init
1043
1044
  	 * @return string|boolean
  	 */
31b7f2792   Kload   Upgrade to ownclo...
1045
1046
  	function exif_imagetype ( $fileName ) {
  		if ( ( $info = getimagesize( $fileName ) ) !== false ) {
03e52840d   Kload   Init
1047
1048
1049
1050
1051
  			return $info[2];
  		}
  		return false;
  	}
  }