# Source for file class.upload.php 0.32

Documentation is available at class.upload.php

Webpage is available at http://www.verot.net/php_class_upload.htm

1. <?php
2. // +------------------------------------------------------------------------+
3. // | class.upload.php |
4. // +------------------------------------------------------------------------+
5. // | Copyright (c) Colin Verot 2003-2010. All rights reserved. |
6. // | Version 0.32 |
7. // | Last modified 15/01/2013 |
8. // | Email colin@verot.net |
9. // | Web http://www.verot.net |
10. // +------------------------------------------------------------------------+
11. // | This program is free software; you can redistribute it and/or modify |
12. // | it under the terms of the GNU General Public License version 2 as |
13. // | published by the Free Software Foundation. |
14. // | |
15. // | This program is distributed in the hope that it will be useful, |
16. // | but WITHOUT ANY WARRANTY; without even the implied warranty of |
17. // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
18. // | GNU General Public License for more details. |
19. // | |
20. // | You should have received a copy of the GNU General Public License |
21. // | along with this program; if not, write to the |
22. // | Free Software Foundation, Inc., 59 Temple Place, Suite 330, |
23. // | Boston, MA 02111-1307 USA |
24. // | |
25. // | Please give credit on sites that use class.upload and submit changes |
26. // | of the script so other people can use them as well. |
27. // | This script is free to use, don't abuse. |
28. // +------------------------------------------------------------------------+
29. //
31. /**
32. * Class upload
33. *
34. * @version 0.32
35. * @author Colin Verot <colin@verot.net>
36. * @license http://opensource.org/licenses/gpl-license.php GNU Public License
37. * @copyright Colin Verot
38. * @package cmf
39. * @subpackage external
40. */
42. /**
43. * Class upload
44. *
45. * <b>What does it do?</b>
46. *
47. * It manages file uploads for you. In short, it manages the uploaded file,
48. * and allows you to do whatever you want with the file, especially if it
49. * is an image, and as many times as you want.
50. *
51. * It is the ideal class to quickly integrate file upload in your site.
52. * If the file is an image, you can convert, resize, crop it in many ways.
53. * You can also apply filters, add borders, text, watermarks, etc...
54. * That's all you need for a gallery script for instance. Supported formats
55. * are PNG, JPG, GIF and BMP.
56. *
57. * You can also use the class to work on local files, which is especially
58. * useful to use the image manipulation features. The class also supports
59. * Flash uploaders.
60. *
61. * The class works with PHP 4 and 5, and its error messages can
62. * be localized at will.
63. *
64. * <b>How does it work?</b>
65. *
66. * You instanciate the class with the $_FILES['my_field'] array
67. * where my_field is the field name from your upload form.
68. * The class will check if the original file has been uploaded
69. * to its temporary location (alternatively, you can instanciate
70. * the class with a local filename).
71. *
72. * You can then set a number of processing variables to act on the file.
73. * For instance, you can rename the file, and if it is an image,
74. * convert and resize it in many ways.
75. * You can also set what will the class do if the file already exists.
76. *
77. * Then you call the function {@link process} to actually perform the actions
78. * according to the processing parameters you set above.
79. * It will create new instances of the original file,
80. * so the original file remains the same between each process.
81. * The file will be manipulated, and copied to the given location.
82. * The processing variables will be reset once it is done.
83. *
84. * You can repeat setting up a new set of processing variables,
85. * and calling {@link process} again as many times as you want.
86. * When you have finished, you can call {@link clean} to delete
87. * the original uploaded file.
88. *
89. * If you don't set any processing parameters and call {@link process}
90. * just after instanciating the class. The uploaded file will be simply
91. * copied to the given location without any alteration or checks.
92. *
93. * Don't forget to add <i>enctype="multipart/form-data"</i> in your form
94. * tag <form> if you want your form to upload the file.
95. *
96. * <b>How to use it?</b><br>
97. * Create a simple HTML file, with a form such as:
98. * <pre>
99. * <form enctype="multipart/form-data" method="post" action="upload.php">
100. * <input type="file" size="32" name="image_field" value="">
101. * <input type="submit" name="Submit" value="upload">
102. * </form>
103. * </pre>
104. * Create a file called upload.php:
105. * <pre>
106. * $handle = new upload($_FILES['image_field']);
107. * if ($handle->uploaded) {
108. * $handle->file_new_name_body = 'image_resized';
109. * $handle->image_resize = true;
110. * $handle->image_x = 100;
111. * $handle->image_ratio_y = true;
112. * $handle->process('/home/user/files/');
113. * if ($handle->processed) {
114. * echo 'image resized';
115. * $handle->clean();
116. * } else {
117. * echo 'error : ' . $handle->error;
118. * }
119. * }
120. * </pre>
121. *
122. * <b>How to process a file uploaded via XMLHttpRequest?</b><br>
123. * Use the class as following, the rest being the same as above:
124. * <pre>
125. * $handle = new upload('php:'.$_SERVER['HTTP_X_FILE_NAME']);
126. * </pre>
127. * Prefixing the argument with "php:" tells the class to retrieve the uploaded data
128. * in php://input, and the rest is the stream's filename, which is generally in
129. * $_SERVER['HTTP_X_FILE_NAME']. But you can use any other name you see fit:
130. * <pre>
131. * $handle = new upload('php:mycustomname.ext');
132. * </pre>
133. *
134. * <b>How to process local files?</b><br>
135. * Use the class as following, the rest being the same as above:
136. * <pre>
137. * $handle = new upload('/home/user/myfile.jpg');
138. * </pre>
139. *
140. * <b>How to set the language?</b><br>
141. * Instantiate the class with a second argument being the language code:
142. * <pre>
143. * $handle = new upload($_FILES['image_field'], 'fr_FR');
144. * $handle = new upload('/home/user/myfile.jpg', 'fr_FR');
145. * </pre>
146. *
147. * <b>How to output the resulting file or picture directly to the browser?</b><br>
148. * Simply call {@link process}() without an argument (or with null as first argument):
149. * <pre>
150. * $handle = new upload($_FILES['image_field']);
151. * header('Content-type: ' . $handle->file_src_mime);
152. * echo $handle->Process();
153. * die();
154. * </pre>
155. * Or if you want to force the download of the file:
156. * <pre>
157. * $handle = new upload($_FILES['image_field']);
158. * header('Content-type: ' . $handle->file_src_mime);
159. * header("Content-Disposition: attachment; filename=".rawurlencode($handle->file_src_name).";");
160. * echo $handle->Process();
161. * die();
162. * </pre>
163. *
164. * <b>Processing parameters</b> (reset after each process)
165. * <ul>
166. * <li><b>{@link file_new_name_body}</b> replaces the name body (default: null)<br>
167. * <pre>$handle->file_new_name_body = 'new name';</pre></li>
168. * <li><b>{@link file_name_body_add}</b> appends to the name body (default: null)<br>
169. * <pre>$handle->file_name_body_add = '_uploaded';</pre></li>
170. * <li><b>{@link file_name_body_pre}</b> prepends to the name body (default: null)<br>
171. * <pre>$handle->file_name_body_pre = 'thumb_';</pre></li>
172. * <li><b>{@link file_new_name_ext}</b> replaces the file extension (default: null)<br>
173. * <pre>$handle->file_new_name_ext = 'txt';</pre></li>
174. * <li><b>{@link file_safe_name}</b> formats the filename (spaces changed to _) (default: true)<br>
175. * <pre>$handle->file_safe_name = true;</pre></li>
176. * <li><b>{@link file_force_extension}</b> forces an extension if there is't any (default: true)<br>
177. * <pre>$handle->file_force_extension = true;</pre></li>
178. * <li><b>{@link file_overwrite}</b> sets behaviour if file already exists (default: false)<br>
179. * <pre>$handle->file_overwrite = true;</pre></li>
180. * <li><b>{@link file_auto_rename}</b> automatically renames file if it already exists (default: true)<br>
181. * <pre>$handle->file_auto_rename = true;</pre></li>
182. * <li><b>{@link dir_auto_create}</b> automatically creates destination directory if missing (default: true)<br>
183. * <pre>$handle->auto_create_dir = true;</pre></li>
184. * <li><b>{@link dir_auto_chmod}</b> automatically attempts to chmod the destination directory if not writeable (default: true)<br>
185. * <pre>$handle->dir_auto_chmod = true;</pre></li>
186. * <li><b>{@link dir_chmod}</b> chmod used when creating directory or if directory not writeable (default: 0777)<br>
187. * <pre>$handle->dir_chmod = 0777;</pre></li>
188. * <li><b>{@link file_max_size}</b> sets maximum upload size (default: upload_max_filesize from php.ini)<br>
189. * <pre>$handle->file_max_size = '1024'; // 1KB</pre></li>
190. * <li><b>{@link mime_check}</b> sets if the class check the MIME against the {@link allowed} list (default: true)<br>
191. * <pre>$handle->mime_check = true;</pre></li>
192. * <li><b>{@link no_script}</b> sets if the class turns scripts into text files (default: true)<br>
193. * <pre>$handle->no_script = false;</pre></li>
194. * <li><b>{@link allowed}</b> array of allowed mime-types (or one string). wildcard accepted, as in image/* (default: check {@link Init})<br>
195. * <pre>$handle->allowed = array('application/pdf','application/msword', 'image/*');</pre></li>
196. * <li><b>{@link forbidden}</b> array of forbidden mime-types (or one string). wildcard accepted, as in image/* (default: check {@link Init})<br>
197. * <pre>$handle->forbidden = array('application/*');</pre></li>
198. * </ul>
199. * <ul>
200. * <li><b>{@link image_convert}</b> if set, image will be converted (possible values : ''|'png'|'jpeg'|'gif'|'bmp'; default: '')<br>
201. * <pre>$handle->image_convert = 'jpg';</pre></li>
202. * <li><b>{@link image_background_color}</b> if set, will forcibly fill transparent areas with the color, in hexadecimal (default: null)<br>
203. * <pre>$handle->image_background_color = '#FF00FF';</pre></li>
204. * <li><b>{@link image_default_color}</b> fallback color background color for non alpha-transparent output formats, such as JPEG or BMP, in hexadecimal (default: #FFFFFF)<br>
205. * <pre>$handle->image_default_color = '#FF00FF';</pre></li>
206. * <li><b>{@link png_compression}</b> sets the compression level for PNG images, between 1 (fast but large files) and 9 (slow but smaller files) (default: null (Zlib default))<br>
207. * <pre>$handle->png_compression = 9;</pre></li>
208. * <li><b>{@link jpeg_quality}</b> sets the compression quality for JPEG images (default: 85)<br>
209. * <pre>$handle->jpeg_quality = 50;</pre></li>
210. * <li><b>{@link jpeg_size}</b> if set to a size in bytes, will approximate {@link jpeg_quality} so the output image fits within the size (default: null)<br>
211. * <pre>$handle->jpeg_size = 3072;</pre></li>
212. * <li><b>{@link image_interlace}</b> if set to true, the image will be saved interlaced (default: false)<br>
213. * <pre>$handle->image_interlace = true;</pre></li>
214. * </ul>
215. * The following eight settings can be used to invalidate an upload if the file is an image (note that <i>open_basedir</i> restrictions prevent the use of these settings)
216. * <ul>
217. * <li><b>{@link image_max_width}</b> if set to a dimension in pixels, the upload will be invalid if the image width is greater (default: null)<br>
218. * <pre>$handle->image_max_width = 200;</pre></li>
219. * <li><b>{@link image_max_height}</b> if set to a dimension in pixels, the upload will be invalid if the image height is greater (default: null)<br>
220. * <pre>$handle->image_max_height = 100;</pre></li>
221. * <li><b>{@link image_max_pixels}</b> if set to a number of pixels, the upload will be invalid if the image number of pixels is greater (default: null)<br>
222. * <pre>$handle->image_max_pixels = 50000;</pre></li>
223. * <li><b>{@link image_max_ratio}</b> if set to a aspect ratio (width/height), the upload will be invalid if the image apect ratio is greater (default: null)<br>
224. * <pre>$handle->image_max_ratio = 1.5;</pre></li>
225. * <li><b>{@link image_min_width}</b> if set to a dimension in pixels, the upload will be invalid if the image width is lower (default: null)<br>
226. * <pre>$handle->image_min_width = 100;</pre></li>
227. * <li><b>{@link image_min_height}</b> if set to a dimension in pixels, the upload will be invalid if the image height is lower (default: null)<br>
228. * <pre>$handle->image_min_height = 500;</pre></li>
229. * <li><b>{@link image_min_pixels}</b> if set to a number of pixels, the upload will be invalid if the image number of pixels is lower (default: null)<br>
230. * <pre>$handle->image_min_pixels = 20000;</pre></li>
231. * <li><b>{@link image_min_ratio}</b> if set to a aspect ratio (width/height), the upload will be invalid if the image apect ratio is lower (default: null)<br>
232. * <pre>$handle->image_min_ratio = 0.5;</pre></li>
233. * </ul>
234. * <ul>
235. * <li><b>{@link image_resize}</b> determines is an image will be resized (default: false)<br>
236. * <pre>$handle->image_resize = true;</pre></li>
237. * </ul>
238. * The following variables are used only if {@link image_resize} == true
239. * <ul>
240. * <li><b>{@link image_x}</b> destination image width (default: 150)<br>
241. * <pre>$handle->image_x = 100;</pre></li>
242. * <li><b>{@link image_y}</b> destination image height (default: 150)<br>
243. * <pre>$handle->image_y = 200;</pre></li>
244. * </ul>
245. * Use either one of the following
246. * <ul>
247. * <li><b>{@link image_ratio}</b> if true, resize image conserving the original sizes ratio, using {@link image_x} AND {@link image_y} as max sizes if true (default: false)<br>
248. * <pre>$handle->image_ratio = true;</pre></li>
249. * <li><b>{@link image_ratio_crop}</b> if true, resize image conserving the original sizes ratio, using {@link image_x} AND {@link image_y} as max sizes, and cropping excedent to fill the space. setting can also be a string, with one or more from 'TBLR', indicating which side of the image will be kept while cropping (default: false)<br>
250. * <pre>$handle->image_ratio_crop = true;</pre></li>
251. * <li><b>{@link image_ratio_fill}</b> if true, resize image conserving the original sizes ratio, using {@link image_x} AND {@link image_y} as max sizes, fitting the image in the space and coloring the remaining space. setting can also be a string, with one or more from 'TBLR', indicating which side of the space the image will be in (default: false)<br>
252. * <pre>$handle->image_ratio_fill = true;</pre></li>
253. * <li><b>{@link image_ratio_no_zoom_in}</b> same as {@link image_ratio}, but won't resize if the source image is smaller than {@link image_x} x {@link image_y} (default: false)<br>
254. * <pre>$handle->image_ratio_no_zoom_in = true;</pre></li>
255. * <li><b>{@link image_ratio_no_zoom_out}</b> same as {@link image_ratio}, but won't resize if the source image is bigger than {@link image_x} x {@link image_y} (default: false)<br>
256. * <pre>$handle->image_ratio_no_zoom_out = true;</pre></li>
257. * <li><b>{@link image_ratio_x}</b> if true, resize image, calculating {@link image_x} from {@link image_y} and conserving the original sizes ratio (default: false)<br>
258. * <pre>$handle->image_ratio_x = true;</pre></li>
259. * <li><b>{@link image_ratio_y}</b> if true, resize image, calculating {@link image_y} from {@link image_x} and conserving the original sizes ratio (default: false)<br>
260. * <pre>$handle->image_ratio_y = true;</pre></li>
261. * <li><b>{@link image_ratio_pixels}</b> if set to a long integer, resize image, calculating {@link image_y} and {@link image_x} to match a the number of pixels (default: false)<br>
262. * <pre>$handle->image_ratio_pixels = 25000;</pre></li>
263. * </ul>
264. * The following image manipulations require GD2+
265. * <ul>
266. * <li><b>{@link image_brightness}</b> if set, corrects the brightness. value between -127 and 127 (default: null)<br>
267. * <pre>$handle->image_brightness = 40;</pre></li>
268. * <li><b>{@link image_contrast}</b> if set, corrects the contrast. value between -127 and 127 (default: null)<br>
269. * <pre>$handle->image_contrast = 50;</pre></li>
270. * <li><b>{@link image_opacity}</b> if set, changes the image opacity. value between 0 and 100 (default: null)<br>
271. * <pre>$handle->image_opacity = 50;</pre></li>
272. * <li><b>{@link image_tint_color}</b> if set, will tint the image with a color, value as hexadecimal #FFFFFF (default: null)<br>
273. * <pre>$handle->image_tint_color = '#FF0000';</pre></li>
274. * <li><b>{@link image_overlay_color}</b> if set, will add a colored overlay, value as hexadecimal #FFFFFF (default: null)<br>
275. * <pre>$handle->image_overlay_color = '#FF0000';</pre></li>
276. * <li><b>{@link image_overlay_opacity}</b> used when {@link image_overlay_color} is set, determines the opacity (default: 50)<br>
277. * <pre>$handle->image_overlay_opacity = 20;</pre></li>
278. * <li><b>{@link image_negative}</b> inverts the colors in the image (default: false)<br>
279. * <pre>$handle->image_negative = true;</pre></li>
280. * <li><b>{@link image_greyscale}</b> transforms an image into greyscale (default: false)<br>
281. * <pre>$handle->image_greyscale = true;</pre></li>
282. * <li><b>{@link image_threshold}</b> applies a threshold filter. value between -127 and 127 (default: null)<br>
283. * <pre>$handle->image_threshold = 20;</pre></li>
284. * <li><b>{@link image_pixelate}</b> pixelate an image, value is block size (default: null)<br>
285. * <pre>$handle->image_pixelate = 10;</pre></li>
286. * <li><b>{@link image_unsharp}</b> applies an unsharp mask, with alpha transparency support (default: false)<br>
287. * <pre>$handle->image_unsharp = true;</pre></li>
288. * <li><b>{@link image_unsharp_amount}</b> unsharp mask amount, typically 50 - 200 (default: 80)<br>
289. * <pre>$handle->image_unsharp_amount = 120;</pre></li>
290. * <li><b>{@link image_unsharp_radius}</b> unsharp mask radius, typically 0.5 - 1 (default: 0.5)<br>
291. * <pre>$handle->image_unsharp_radius = 1;</pre></li>
292. * <li><b>{@link image_unsharp_threshold}</b> unsharp mask threshold, typically 0 - 5 (default: 1)<br>
293. * <pre>$handle->image_unsharp_threshold = 0;</pre></li>
294. * </ul>
295. * <ul>
296. * <li><b>{@link image_text}</b> creates a text label on the image, value is a string, with eventual replacement tokens (default: null)<br>
297. * <pre>$handle->image_text = 'test';</pre></li>
298. * <li><b>{@link image_text_direction}</b> text label direction, either 'h' horizontal or 'v' vertical (default: 'h')<br>
299. * <pre>$handle->image_text_direction = 'v';</pre></li>
300. * <li><b>{@link image_text_color}</b> text color for the text label, in hexadecimal (default: #FFFFFF)<br>
301. * <pre>$handle->image_text_color = '#FF0000';</pre></li>
302. * <li><b>{@link image_text_opacity}</b> text opacity on the text label, integer between 0 and 100 (default: 100)<br>
303. * <pre>$handle->image_text_opacity = 50;</pre></li>
304. * <li><b>{@link image_text_background}</b> text label background color, in hexadecimal (default: null)<br>
305. * <pre>$handle->image_text_background = '#FFFFFF';</pre></li>
306. * <li><b>{@link image_text_background_opacity}</b> text label background opacity, integer between 0 and 100 (default: 100)<br>
307. * <pre>$handle->image_text_background_opacity = 50;</pre></li>
308. * <li><b>{@link image_text_font}</b> built-in font for the text label, from 1 to 5. 1 is the smallest (default: 5)<br>
309. * <pre>$handle->image_text_font = 4;</pre></li>
310. * <li><b>{@link image_text_x}</b> absolute text label position, in pixels from the left border. can be negative (default: null)<br>
311. * <pre>$handle->image_text_x = 5;</pre></li>
312. * <li><b>{@link image_text_y}</b> absolute text label position, in pixels from the top border. can be negative (default: null)<br>
313. * <pre>$handle->image_text_y = 5;</pre></li>
314. * <li><b>{@link image_text_position}</b> text label position withing the image, a combination of one or two from 'TBLR': top, bottom, left, right (default: null)<br>
315. * <pre>$handle->image_text_position = 'LR';</pre></li>
316. * <li><b>{@link image_text_padding}</b> text label padding, in pixels. can be overridden by {@link image_text_padding_x} and {@link image_text_padding_y} (default: 0)<br>
317. * <pre>$handle->image_text_padding = 5;</pre></li>
318. * <li><b>{@link image_text_padding_x}</b> text label horizontal padding (default: null)<br>
319. * <pre>$handle->image_text_padding_x = 2;</pre></li>
320. * <li><b>{@link image_text_padding_y}</b> text label vertical padding (default: null)<br>
321. * <pre>$handle->image_text_padding_y = 10;</pre></li>
322. * <li><b>{@link image_text_alignment}</b> text alignment when text has multiple lines, either 'L', 'C' or 'R' (default: 'C')<br>
323. * <pre>$handle->image_text_alignment = 'R';</pre></li>
324. * <li><b>{@link image_text_line_spacing}</b> space between lines in pixels, when text has multiple lines (default: 0)<br>
325. * <pre>$handle->image_text_line_spacing = 3;</pre></li>
326. * </ul>
327. * <ul>
328. * <li><b>{@link image_flip}</b> flips image, wither 'h' horizontal or 'v' vertical (default: null)<br>
329. * <pre>$handle->image_flip = 'h';</pre></li>
330. * <li><b>{@link image_rotate}</b> rotates image. possible values are 90, 180 and 270 (default: null)<br>
331. * <pre>$handle->image_rotate = 90;</pre></li>
332. * <li><b>{@link image_crop}</b> crops image. accepts 4, 2 or 1 values as 'T R B L' or 'TB LR' or 'TBLR'. dimension can be 20, or 20px or 20% (default: null)<br>
333. * <pre>$handle->image_crop = array(50,40,30,20); OR '-20 20%'...</pre></li>
334. * <li><b>{@link image_precrop}</b> crops image, before an eventual resizing. accepts 4, 2 or 1 values as 'T R B L' or 'TB LR' or 'TBLR'. dimension can be 20, or 20px or 20% (default: null)<br>
335. * <pre>$handle->image_precrop = array(50,40,30,20); OR '-20 20%'...</pre></li>
336. * </ul>
337. * <ul>
338. * <li><b>{@link image_bevel}</b> adds a bevel border to the image. value is thickness in pixels (default: null)<br>
339. * <pre>$handle->image_bevel = 20;</pre></li>
340. * <li><b>{@link image_bevel_color1}</b> top and left bevel color, in hexadecimal (default: #FFFFFF)<br>
341. * <pre>$handle->image_bevel_color1 = '#FFFFFF';</pre></li>
342. * <li><b>{@link image_bevel_color2}</b> bottom and right bevel color, in hexadecimal (default: #000000)<br>
343. * <pre>$handle->image_bevel_color2 = '#000000';</pre></li>
344. * <li><b>{@link image_border}</b> adds a unicolor border to the image. accepts 4, 2 or 1 values as 'T R B L' or 'TB LR' or 'TBLR'. dimension can be 20, or 20px or 20% (default: null)<br>
345. * <pre>$handle->image_border = '3px'; OR '-20 20%' OR array(3,2)...</pre></li>
346. * <li><b>{@link image_border_color}</b> border color, in hexadecimal (default: #FFFFFF)<br>
347. * <pre>$handle->image_border_color = '#FFFFFF';</pre></li>
348. * <li><b>{@link image_border_opacity}</b> border opacity, integer between 0 and 100 (default: 100)<br>
349. * <pre>$handle->image_border_opacity = 50;</pre></li>
350. * <li><b>{@link image_border_transparent}</b> adds a fading-to-transparent border to the image. accepts 4, 2 or 1 values as 'T R B L' or 'TB LR' or 'TBLR'. dimension can be 20, or 20px or 20% (default: null)<br>
351. * <pre>$handle->image_border_transparent = '3px'; OR '-20 20%' OR array(3,2)...</pre></li>
352. * <li><b>{@link image_frame}</b> type of frame: 1=flat 2=crossed (default: null)<br>
353. * <pre>$handle->image_frame = 2;</pre></li>
354. * <li><b>{@link image_frame_colors}</b> list of hex colors, in an array or a space separated string (default: '#FFFFFF #999999 #666666 #000000')<br>
355. * <pre>$handle->image_frame_colors = array('#999999', '#FF0000', '#666666', '#333333', '#000000');</pre></li>
356. * <li><b>{@link image_frame_opacity}</b> frame opacity, integer between 0 and 100 (default: 100)<br>
357. * <pre>$handle->image_frame_opacity = 50;</pre></li>
358. * </ul>
359. * <ul>
360. * <li><b>{@link image_watermark}</b> adds a watermark on the image, value is a local filename. accepted files are GIF, JPG, BMP, PNG and PNG alpha (default: null)<br>
361. * <pre>$handle->image_watermark = 'watermark.png';</pre></li>
362. * <li><b>{@link image_watermark_x}</b> absolute watermark position, in pixels from the left border. can be negative (default: null)<br>
363. * <pre>$handle->image_watermark_x = 5;</pre></li>
364. * <li><b>{@link image_watermark_y}</b> absolute watermark position, in pixels from the top border. can be negative (default: null)<br>
365. * <pre>$handle->image_watermark_y = 5;</pre></li>
366. * <li><b>{@link image_watermark_position}</b> watermark position withing the image, a combination of one or two from 'TBLR': top, bottom, left, right (default: null)<br>
367. * <pre>$handle->image_watermark_position = 'LR';</pre></li>
368. * <li><b>{@link image_watermark_no_zoom_in}</b> prevents the watermark to be resized up if it is smaller than the image (default: true)<br>
369. * <pre>$handle->image_watermark_no_zoom_in = false;</pre></li>
370. * <li><b>{@link image_watermark_no_zoom_out}</b> prevents the watermark to be resized down if it is bigger than the image (default: false)<br>
371. * <pre>$handle->image_watermark_no_zoom_out = true;</pre></li>
372. * </ul>
373. * <ul>
374. * <li><b>{@link image_reflection_height}</b> if set, a reflection will be added. Format is either in pixels or percentage, such as 40, '40', '40px' or '40%' (default: null)<br>
375. * <pre>$handle->image_reflection_height = '25%';</pre></li>
376. * <li><b>{@link image_reflection_space}</b> space in pixels between the source image and the reflection, can be negative (default: null)<br>
377. * <pre>$handle->image_reflection_space = 3;</pre></li>
378. * <li><b>{@link image_reflection_color}</b> reflection background color, in hexadecimal. Now deprecated in favor of {@link image_default_color} (default: #FFFFFF)<br>
379. * <pre>$handle->image_default_color = '#000000';</pre></li>
380. * <li><b>{@link image_reflection_opacity}</b> opacity level at which the reflection starts, integer between 0 and 100 (default: 60)<br>
381. * <pre>$handle->image_reflection_opacity = 60;</pre></li>
382. * </ul>
383. *
384. * <b>Values that can be read before calling {@link process}()</b>
385. * <ul>
386. * <li><b>{@link file_src_name}</b> Source file name</li>
387. * <li><b>{@link file_src_name_body}</b> Source file name body</li>
388. * <li><b>{@link file_src_name_ext}</b> Source file extension</li>
389. * <li><b>{@link file_src_pathname}</b> Source file complete path and name</li>
390. * <li><b>{@link file_src_mime}</b> Source file mime type</li>
391. * <li><b>{@link file_src_size}</b> Source file size in bytes</li>
392. * <li><b>{@link file_src_error}</b> Upload error code</li>
393. * <li><b>{@link file_is_image}</b> Boolean flag, true if the file is a supported image type</li>
394. * </ul>
395. * If the file is a supported image type (and <i>open_basedir</i> restrictions allow it)
396. * <ul>
397. * <li><b>{@link image_src_x}</b> Source file width in pixels</li>
398. * <li><b>{@link image_src_y}</b> Source file height in pixels</li>
399. * <li><b>{@link image_src_pixels}</b> Source file number of pixels</li>
400. * <li><b>{@link image_src_type}</b> Source file type (png, jpg, gif or bmp)</li>
401. * <li><b>{@link image_src_bits}</b> Source file color depth</li>
402. * </ul>
403. *
404. * <b>Values that can be read after calling {@link process}()</b>
405. * <ul>
406. * <li><b>{@link file_dst_path}</b> Destination file path</li>
407. * <li><b>{@link file_dst_name_body}</b> Destination file name body</li>
408. * <li><b>{@link file_dst_name_ext}</b> Destination file extension</li>
409. * <li><b>{@link file_dst_name}</b> Destination file name</li>
410. * <li><b>{@link file_dst_pathname}</b> Destination file complete path and name</li>
411. * </ul>
412. * If the file is a supported image type
413. * <ul>
414. * <li><b>{@link image_dst_x}</b> Destination file width</li>
415. * <li><b>{@link image_dst_y}</b> Destination file height</li>
416. * <li><b>{@link image_convert}</b> Destination file format</li>
417. * </ul>
418. *
419. * <b>Requirements</b>
420. *
421. * Most of the image operations require GD. GD2 is greatly recommended
422. *
423. * The class requires PHP 4.3+, and is compatible with PHP5
424. *
425. * <b>Changelog</b>
426. * <ul>
427. * <li><b>v 0.32</b> 15/01/2013<br>
428. * - add support for XMLHttpRequest uploads<br>
429. * - added {@link image_pixelate}<br>
430. * - added {@link image_interlace}<br>
431. * - added {@link png_compression} to change PNG compressoin level<br>
432. * - deactivate exec() if Suhosin is enabled<br>
433. * - add more extension to dangerous scripts detection<br>
434. * - imagejpeg takes null as second argument since PHP 5.4<br>
435. * - default PECL Fileinfo MAGIC path to null<br>
436. * - set gd.jpeg_ignore_warning to true by default<br>
437. * - fixed file name normalization</li>
438. * <li><b>v 0.31</b> 11/04/2011<br>
439. * - added application/x-rar MIME type<br>
440. * - make sure exec() and ini_get_all()function are not disabled if we want to use them<br>
441. * - make sure that we don't divide by zero when calculating JPEG size<br>
442. * - {@link allowed} and {@link forbidden} can now accept strings<br>
443. * - try to guess the file extension from the MIME type if there is no file extension<br>
444. * - better class properties when changing the file extension<br>
445. * - added {@link file_force_extension} to allow extension-less files if needed<br>
446. * - better file safe conversion of the filename<br>
447. * - allow shorthand byte values, such as 1K, 2M, 3G for {@link file_max_size} and {@link jpeg_size}<br>
448. * - added {@link image_opacity} to change picture opacity<br>
449. * - added {@link image_border_opacity} to allow semi-transparent borders<br>
450. * - added {@link image_frame_opacity} to allow semi-transparent frames<br>
451. * - added {@link image_border_transparent} to allow borders fading to transparent<br>
452. * - duplicated {@link image_overlay_percent} into {@link image_overlay_opacity}<br>
453. * - duplicated {@link image_text_percent} into {@link image_text_opacity}<br>
454. * - duplicated {@link image_text_background_percent} into {@link image_text_background_opacity}</li>
455. * <li><b>v 0.30</b> 05/09/2010<br>
456. * - implemented an unsharp mask, with alpha transparency support, activated if {@link image_unsharp} is true. added {@link image_unsharp_amount}, {@link image_unsharp_radius}, and {@link image_unsharp_threshold}<br>
457. * - added text/rtf MIME type, and no_script exception<br>
458. * - corrected bug when {@link no_script} is activated and several process() are called<br>
459. * - better error handling for finfo<br>
460. * - display upload_max_filesize information from php.ini in the log<br>
461. * - automatic extension for extension-less images<br>
462. * - fixed {@link image_ratio_fill} top and left filling<br>
463. * - fixed alphablending issue when applying a transparent PNG watermark on a transparent PNG<br>
464. * - added {@link image_watermark_no_zoom_in} and {@link image_watermark_no_zoom_out} to allow the watermark to be resized down (or up) to fit in the image. By default, the watermark may be resized down, but not up.</li>
465. * <li><b>v 0.29</b> 03/02/2010<br>
466. * - added protection against malicious images<br>
467. * - added zip and torrent MIME type<br>
468. * - replaced split() with explode()<br>
469. * - initialise image_dst_x/y with image_src_x/y<br>
470. * - removed {@link mime_fileinfo}, {@link mime_file}, {@link mime_magic} and {@link mime_getimagesize} from the docs since they are used before {@link process}<br>
471. * - added more extensions and MIME types<br>
472. * - improved MIME type validation<br>
473. * - improved logging</li>
474. * <li><b>v 0.28</b> 10/08/2009<br>
475. * - replaced ereg functions to be compatible with PHP 5.3<br>
476. * - added flv MIME type<br>
477. * - improved MIME type detection<br>
478. * - added {@link file_name_body_pre} to prepend a string to the file name<br>
479. * - added {@link mime_fileinfo}, {@link mime_file}, {@link mime_magic} and {@link mime_getimagesize} so that it is possible to deactivate some MIME type checking method<br>
480. * - use exec() rather than shell_exec(), to play better with safe mode <br>
481. * - added some error messages<br>
482. * - fix bug when checking on conditions, {@link processed} wasn't propagated properly</li>
483. * <li><b>v 0.27</b> 14/05/2009<br>
484. * - look for the language files directory from __FILE__<br>
485. * - deactivate {@link file_auto_rename} if {@link file_overwrite} is set<br>
486. * - improved transparency replacement for true color images<br>
487. * - fixed calls to newer version of UNIX file utility<br>
488. * - fixed error when using PECL Fileinfo extension in SAFE MODE, and when using the finfo class<br>
489. * - added {@link image_precrop} to crop the image before an eventual resizing</li>
490. * <li><b>v 0.26</b> 13/11/2008<br>
491. * - rewrote conversion from palette to true color to handle transparency better<br>
492. * - fixed imagecopymergealpha() when the overlayed image is of wrong dimensions<br>
493. * - fixed imagecreatenew() when the image to create have less than 1 pixels width or height<br>
494. * - rewrote MIME type detection to be more secure and not rely on browser information; now using Fileinfo PECL extension, UNIX file() command, MIME magic, and getimagesize(), in that order<br>
495. * - added support for Flash uploaders<br>
496. * - some bug fixing and error handling</li>
497. * <li><b>v 0.25</b> 17/11/2007<br>
498. * - added translation files and mechanism to instantiate the class with a language different from English<br>
499. * - added {@link forbidden} to set an array of forbidden MIME types<br>
500. * - implemented support for simple wildcards in {@link allowed} and {@link forbidden}, such as image/*<br>
501. * - preset the file extension to the desired conversion format when converting an image<br>
502. * - added read and write support for BMP images<br>
503. * - added a flag {@link file_is_image} to determine if the file is a supported image type<br>
504. * - the class now provides some information about the image, before calling {@link process}(). Available are {@link image_src_x}, {@link image_src_y} and the newly introduced {@link image_src_bits}, {@link image_src_pixels} and {@link image_src_type}. Note that this will not work if <i>open_basedir</i> restrictions are in place<br>
505. * - improved logging; now provides useful system information<br>
506. * - added some more pre-processing checks for files that are images: {@link image_max_width}, {@link image_max_height}, {@link image_max_pixels}, {@link image_max_ratio}, {@link image_min_width}, {@link image_min_height}, {@link image_min_pixels} and {@link image_min_ratio}<br>
507. * - added {@link image_ratio_pixels} to resize an image to a number of pixels, keeping aspect ratio<br>
508. * - added {@link image_is_palette} and {@link image_is_transparent} and {@link image_transparent_color} for GIF images<br>
509. * - added {@link image_default_color} to define a fallback color for non alpha-transparent output formats, such as JPEG or BMP<br>
510. * - changed {@link image_background_color}, which now forces transparent areas to be painted<br>
511. * - improved reflections and color overlays so that it works with alpha transparent images<br>
512. * - {@link image_reflection_color} is now deprecated in favour of {@link image_default_color}<br />
513. * - transparent PNGs are now processed in true color, and fully preserving the alpha channel when doing merges<br>
514. * - transparent GIFs are now automatically detected. {@link preserve_transparency} is deprecated<br>
515. * - transparent true color images can be saved as GIF while retaining transparency, semi transparent areas being merged with {@link image_default_color}<br>
516. * - transparent true color images can be saved as JPG/BMP with the semi transparent areas being merged with {@link image_default_color}<br>
517. * - fixed conversion of images to true color<br>
518. * - the class can now output the uploaded files content as the return value of process() if the function is called with an empty or null argumenti, or no argument</li>
519. * <li><b>v 0.24</b> 25/05/2007<br>
520. * - added {@link image_background_color}, to set the default background color of an image<br>
521. * - added possibility of using replacement tokens in text labels<br>
522. * - changed default JPEG quality to 85<br>
523. * - fixed a small bug when using greyscale filter and associated filters<br>
524. * - added {@link image_ratio_fill} in order to fit an image within some dimensions and color the remaining space. Very similar to {@link image_ratio_crop}<br>
525. * - improved the recursive creation of directories<br>
526. * - the class now converts palette based images to true colors before doing graphic manipulations</li>
527. * <li><b>v 0.23</b> 23/12/2006<br>
528. * - fixed a bug when processing more than once the same uploaded file. If there is an open_basedir restriction, the class now creates a temporary file for the first call to process(). This file will be used for subsequent processes, and will be deleted upon calling clean()</li>
529. * <li><b>v 0.22</b> 16/12/2006<br>
530. * - added automatic creation of a temporary file if the upload directory is not within open_basedir<br>
531. * - fixed a bug which was preventing to work on a local file by overwriting it with its processed copy<br>
532. * - added MIME types video/x-ms-wmv and image/x-png and fixed PNG support for IE weird MIME types<br>
533. * - modified {@link image_ratio_crop} so it can accept one or more from string 'TBLR', determining which side of the image is kept while cropping<br>
534. * - added support for multiple lines in the text, using "\n" as a line break<br>
535. * - added {@link image_text_line_spacing} which allow to set the space between several lines of text<br>
536. * - added {@link image_text_alignment} which allow to set the alignment when text has several lines<br>
537. * - {@link image_text_font} can now be set to the path of a GDF font to load external fonts<br>
538. * - added {@link image_reflection_height} to create a reflection of the source image, which height is in pixels or percentage<br>
539. * - added {@link image_reflection_space} to set the space in pixels between the source image and the reflection<br>
540. * - added {@link image_reflection_color} to set the reflection background color<br>
541. * - added {@link image_reflection_opacity} to set the initial level of opacity of the reflection</li>
542. * <li><b>v 0.21</b> 30/09/2006<br>
543. * - added {@link image_ratio_crop} which resizes within {@link image_x} and {@link image_y}, keeping ratio, but filling the space by cropping excedent of image<br>
544. * - added {@link mime_check}, which default is true, to set checks against {@link allowed} MIME list<br>
545. * - if MIME is empty, the class now triggers an error<br>
546. * - color #000000 is OK for {@link image_text_color}, and related text transparency bug fixed<br>
547. * - {@link gd_version}() now uses gd_info(), or else phpinfo()<br>
548. * - fixed path issue when the destination path has no trailing slash on Windows systems <br>
549. * - removed inline functions to be fully PHP5 compatible </li>
550. * <li><b>v 0.20</b> 11/08/2006<br>
551. * - added some more error checking and messages (GD presence, permissions...)<br>
552. * - fix when uploading files without extension<br>
553. * - changed values for {@link image_brightness} and {@link image_contrast} to be between -127 and 127<br>
554. * - added {@link dir_auto_create} to automatically and recursively create destination directory if missing.<br>
555. * - added {@link dir_auto_chmod} to automatically chmod the destination directory if not writeable.<br>
556. * - added {@link dir_chmod} to set the default chmod to use.<br>
557. * - added {@link image_crop} to crop images<br>
558. * - added {@link image_negative} to invert the colors on the image<br>
559. * - added {@link image_greyscale} to turn the image into greyscale<br>
560. * - added {@link image_threshold} to apply a threshold filter on the image<br>
561. * - added {@link image_bevel}, {@link image_bevel_color1} and {@link image_bevel_color2} to add a bevel border<br>
562. * - added {@link image_border} and {@link image_border_color} to add a single color border<br>
563. * - added {@link image_frame} and {@link image_frame_colors} to add a multicolored frame</li>
564. * <li><b>v 0.19</b> 29/03/2006<br>
565. * - class is now compatible i18n (thanks Sylwester).<br>
566. * - the class can mow manipulate local files, not only uploaded files (instanciate the class with a local filename).<br>
567. * - {@link file_safe_name} has been improved a bit.<br>
568. * - added {@link image_brightness}, {@link image_contrast}, {@link image_tint_color}, {@link image_overlay_color} and {@link image_overlay_percent} to do color manipulation on the images.<br>
569. * - added {@link image_text} and all derivated settings to add a text label on the image.<br>
570. * - added {@link image_watermark} and all derivated settings to add a watermark image on the image.<br>
571. * - added {@link image_flip} and {@link image_rotate} for more image manipulations<br>
572. * - added {@link jpeg_size} to calculate the JPG compression quality in order to fit within one filesize.</li>
573. * <li><b>v 0.18</b> 02/02/2006<br>
574. * - added {@link no_script} to turn dangerous scripts into text files.<br>
575. * - added {@link mime_magic_check} to set the class to use mime_magic.<br>
576. * - added {@link preserve_transparency} *experimental*. Thanks Gregor.<br>
577. * - fixed size and mime checking, wasn't working :/ Thanks Willem.<br>
578. * - fixed memory leak when resizing images.<br>
579. * - when resizing, it is not necessary anymore to set {@link image_convert}.<br>
580. * - il is now possible to simply convert an image, with no resizing.<br>
581. * - sets the default {@link file_max_size} to upload_max_filesize from php.ini. Thanks Edward</li>
582. * <li><b>v 0.17</b> 28/05/2005<br>
583. * - the class can be used with any version of GD.<br>
584. * - added security check on the file with a list of mime-types.<br>
585. * - changed the license to GPL v2 only</li>
586. * <li><b>v 0.16</b> 19/05/2005<br>
587. * - added {@link file_auto_rename} automatic file renaming if the same filename already exists.<br>
588. * - added {@link file_safe_name} safe formatting of the filename (spaces to _underscores so far).<br>
589. * - added some more error reporting to avoid crash if GD is not present</li>
590. * <li><b>v 0.15</b> 16/04/2005<br>
591. * - added JPEG compression quality setting. Thanks Vad</li>
592. * <li><b>v 0.14</b> 14/03/2005<br>
593. * - reworked the class file to allow parsing with phpDocumentor</li>
594. * <li><b>v 0.13</b> 07/03/2005<br>
595. * - fixed a bug with {@link image_ratio}. Thanks Justin.<br>
596. * - added {@link image_ratio_no_zoom_in} and {@link image_ratio_no_zoom_out} </li>
597. * <li><b>v 0.12</b> 21/01/2005<br>
598. * - added {@link image_ratio} to resize within max values, keeping image ratio</li>
599. * <li><b>v 0.11</b> 22/08/2003<br>
600. * - update for GD2 (changed imageresized() into imagecopyresampled() and imagecreate() into imagecreatetruecolor())</li>
601. * </ul>
602. *
603. * @package cmf
604. * @subpackage external
605. */
606. class upload {
609. /**
610. * Class version
611. *
612. * @access public
613. * @var string
614. */
615. var $version;
617. /**
618. * Uploaded file name
619. *
620. * @access public
621. * @var string
622. */
623. var $file_src_name;
625. /**
626. * Uploaded file name body (i.e. without extension)
627. *
628. * @access public
629. * @var string
630. */
631. var $file_src_name_body;
633. /**
634. * Uploaded file name extension
635. *
636. * @access public
637. * @var string
638. */
639. var $file_src_name_ext;
641. /**
642. * Uploaded file MIME type
643. *
644. * @access public
645. * @var string
646. */
647. var $file_src_mime;
649. /**
650. * Uploaded file size, in bytes
651. *
652. * @access public
653. * @var double
654. */
655. var $file_src_size;
657. /**
658. * Holds eventual PHP error code from $_FILES
659. *
660. * @access public
661. * @var string
662. */
663. var $file_src_error;
665. /**
666. * Uloaded file name, including server path
667. *
668. * @access public
669. * @var string
670. */
671. var $file_src_pathname;
673. /**
674. * Uloaded file name temporary copy
675. *
676. * @access private
677. * @var string
678. */
679. var $file_src_temp;
681. /**
682. * Destination file name
683. *
684. * @access public
685. * @var string
686. */
687. var $file_dst_path;
689. /**
690. * Destination file name
691. *
692. * @access public
693. * @var string
694. */
695. var $file_dst_name;
697. /**
698. * Destination file name body (i.e. without extension)
699. *
700. * @access public
701. * @var string
702. */
703. var $file_dst_name_body;
705. /**
706. * Destination file extension
707. *
708. * @access public
709. * @var string
710. */
711. var $file_dst_name_ext;
713. /**
714. * Destination file name, including path
715. *
716. * @access public
717. * @var string
718. */
719. var $file_dst_pathname;
721. /**
722. * Source image width
723. *
724. * @access public
725. * @var integer
726. */
727. var $image_src_x;
729. /**
730. * Source image height
731. *
732. * @access public
733. * @var integer
734. */
735. var $image_src_y;
737. /**
738. * Source image color depth
739. *
740. * @access public
741. * @var integer
742. */
743. var $image_src_bits;
745. /**
746. * Number of pixels
747. *
748. * @access public
749. * @var long
750. */
751. var $image_src_pixels;
753. /**
754. * Type of image (png, gif, jpg or bmp)
755. *
756. * @access public
757. * @var string
758. */
759. var $image_src_type;
761. /**
762. * Destination image width
763. *
764. * @access public
765. * @var integer
766. */
767. var $image_dst_x;
769. /**
770. * Destination image height
771. *
772. * @access public
773. * @var integer
774. */
775. var $image_dst_y;
777. /**
778. * Supported image formats
779. *
780. * @access private
781. * @var array
782. */
783. var $image_supported;
785. /**
786. * Flag to determine if the source file is an image
787. *
788. * @access public
789. * @var boolean
790. */
791. var $file_is_image;
793. /**
794. * Flag set after instanciating the class
795. *
796. * Indicates if the file has been uploaded properly
797. *
798. * @access public
799. * @var bool
800. */
801. var $uploaded;
803. /**
804. * Flag stopping PHP upload checks
805. *
806. * Indicates whether we instanciated the class with a filename, in which case
807. * we will not check on the validity of the PHP *upload*
808. *
809. * This flag is automatically set to true when working on a local file
810. *
811. * Warning: for uploads, this flag MUST be set to false for security reason
812. *
813. * @access public
814. * @var bool
815. */
816. var $no_upload_check;
818. /**
819. * Flag set after calling a process
820. *
821. * Indicates if the processing, and copy of the resulting file went OK
822. *
823. * @access public
824. * @var bool
825. */
826. var $processed;
828. /**
829. * Holds eventual error message in plain english
830. *
831. * @access public
832. * @var string
833. */
834. var $error;
836. /**
837. * Holds an HTML formatted log
838. *
839. * @access public
840. * @var string
841. */
842. var $log;
845. // overiddable processing variables
848. /**
849. * Set this variable to replace the name body (i.e. without extension)
850. *
851. * @access public
852. * @var string
853. */
854. var $file_new_name_body;
856. /**
857. * Set this variable to append a string to the file name body
858. *
859. * @access public
860. * @var string
861. */
862. var $file_name_body_add;
864. /**
865. * Set this variable to prepend a string to the file name body
866. *
867. * @access public
868. * @var string
869. */
870. var $file_name_body_pre;
872. /**
873. * Set this variable to change the file extension
874. *
875. * @access public
876. * @var string
877. */
878. var $file_new_name_ext;
880. /**
881. * Set this variable to format the filename (spaces changed to _)
882. *
883. * @access public
884. * @var boolean
885. */
886. var $file_safe_name;
888. /**
889. * Forces an extension if the source file doesn't have one
890. *
891. * If the file is an image, then the correct extension will be added
892. * Otherwise, a .txt extension will be chosen
893. *
894. * @access public
895. * @var boolean
896. */
897. var $file_force_extension;
899. /**
900. * Set this variable to false if you don't want to check the MIME against the allowed list
901. *
902. * This variable is set to true by default for security reason
903. *
904. * @access public
905. * @var boolean
906. */
907. var $mime_check;
909. /**
910. * Set this variable to false in the init() function if you don't want to check the MIME
911. * with Fileinfo PECL extension. On some systems, Fileinfo is known to be buggy, and you
912. * may want to deactivate it in the class code directly.
913. *
914. * You can also set it with the path of the magic database file.
915. * If set to true, the class will try to read the MAGIC environment variable
916. * and if it is empty, will default to the system's default
917. * If set to an empty string, it will call finfo_open without the path argument
918. *
919. * This variable is set to true by default for security reason
920. *
921. * @access public
922. * @var boolean
923. */
924. var $mime_fileinfo;
926. /**
927. * Set this variable to false in the init() function if you don't want to check the MIME
928. * with UNIX file() command
929. *
930. * This variable is set to true by default for security reason
931. *
932. * @access public
933. * @var boolean
934. */
935. var $mime_file;
937. /**
938. * Set this variable to false in the init() function if you don't want to check the MIME
939. * with the magic.mime file
940. *
941. * The function mime_content_type() will be deprecated,
942. * and this variable will be set to false in a future release
943. *
944. * This variable is set to true by default for security reason
945. *
946. * @access public
947. * @var boolean
948. */
949. var $mime_magic;
951. /**
952. * Set this variable to false in the init() function if you don't want to check the MIME
953. * with getimagesize()
954. *
955. * The class tries to get a MIME type from getimagesize()
956. * If no MIME is returned, it tries to guess the MIME type from the file type
957. *
958. * This variable is set to true by default for security reason
959. *
960. * @access public
961. * @var boolean
962. */
963. var $mime_getimagesize;
965. /**
966. * Set this variable to false if you don't want to turn dangerous scripts into simple text files
967. *
968. * @access public
969. * @var boolean
970. */
971. var $no_script;
973. /**
974. * Set this variable to true to allow automatic renaming of the file
975. * if the file already exists
976. *
977. * Default value is true
978. *
979. * For instance, on uploading foo.ext,<br>
980. * if foo.ext already exists, upload will be renamed foo_1.ext<br>
981. * and if foo_1.ext already exists, upload will be renamed foo_2.ext<br>
982. *
983. * Note that this option doesn't have any effect if {@link file_overwrite} is true
984. *
985. * @access public
986. * @var bool
987. */
988. var $file_auto_rename;
990. /**
991. * Set this variable to true to allow automatic creation of the destination
992. * directory if it is missing (works recursively)
993. *
994. * Default value is true
995. *
996. * @access public
997. * @var bool
998. */
999. var $dir_auto_create;
1001. /**
1002. * Set this variable to true to allow automatic chmod of the destination
1003. * directory if it is not writeable
1004. *
1005. * Default value is true
1006. *
1007. * @access public
1008. * @var bool
1009. */
1010. var $dir_auto_chmod;
1012. /**
1013. * Set this variable to the default chmod you want the class to use
1014. * when creating directories, or attempting to write in a directory
1015. *
1016. * Default value is 0777 (without quotes)
1017. *
1018. * @access public
1019. * @var bool
1020. */
1021. var $dir_chmod;
1023. /**
1024. * Set this variable tu true to allow overwriting of an existing file
1025. *
1026. * Default value is false, so no files will be overwritten
1027. *
1028. * @access public
1029. * @var bool
1030. */
1031. var $file_overwrite;
1033. /**
1034. * Set this variable to change the maximum size in bytes for an uploaded file
1035. *
1036. * Default value is the value <i>upload_max_filesize</i> from php.ini
1037. *
1038. * Value in bytes (integer) or shorthand byte values (string) is allowed.
1039. * The available options are K (for Kilobytes), M (for Megabytes) and G (for Gigabytes)
1040. *
1041. * @access public
1042. * @var double
1043. */
1044. var $file_max_size;
1046. /**
1047. * Set this variable to true to resize the file if it is an image
1048. *
1049. * You will probably want to set {@link image_x} and {@link image_y}, and maybe one of the ratio variables
1050. *
1051. * Default value is false (no resizing)
1052. *
1053. * @access public
1054. * @var bool
1055. */
1056. var $image_resize;
1058. /**
1059. * Set this variable to convert the file if it is an image
1060. *
1061. * Possibles values are : ''; 'png'; 'jpeg'; 'gif'; 'bmp'
1062. *
1063. * Default value is '' (no conversion)<br>
1064. * If {@link resize} is true, {@link convert} will be set to the source file extension
1065. *
1066. * @access public
1067. * @var string
1068. */
1069. var $image_convert;
1071. /**
1072. * Set this variable to the wanted (or maximum/minimum) width for the processed image, in pixels
1073. *
1074. * Default value is 150
1075. *
1076. * @access public
1077. * @var integer
1078. */
1079. var $image_x;
1081. /**
1082. * Set this variable to the wanted (or maximum/minimum) height for the processed image, in pixels
1083. *
1084. * Default value is 150
1085. *
1086. * @access public
1087. * @var integer
1088. */
1089. var $image_y;
1091. /**
1092. * Set this variable to keep the original size ratio to fit within {@link image_x} x {@link image_y}
1093. *
1094. * Default value is false
1095. *
1096. * @access public
1097. * @var bool
1098. */
1099. var $image_ratio;
1101. /**
1102. * Set this variable to keep the original size ratio to fit within {@link image_x} x {@link image_y}
1103. *
1104. * The image will be resized as to fill the whole space, and excedent will be cropped
1105. *
1106. * Value can also be a string, one or more character from 'TBLR' (top, bottom, left and right)
1107. * If set as a string, it determines which side of the image is kept while cropping.
1108. * By default, the part of the image kept is in the center, i.e. it crops equally on both sides
1109. *
1110. * Default value is false
1111. *
1112. * @access public
1113. * @var mixed
1114. */
1115. var $image_ratio_crop;
1117. /**
1118. * Set this variable to keep the original size ratio to fit within {@link image_x} x {@link image_y}
1119. *
1120. * The image will be resized to fit entirely in the space, and the rest will be colored.
1121. * The default color is white, but can be set with {@link image_default_color}
1122. *
1123. * Value can also be a string, one or more character from 'TBLR' (top, bottom, left and right)
1124. * If set as a string, it determines in which side of the space the image is displayed.
1125. * By default, the image is displayed in the center, i.e. it fills the remaining space equally on both sides
1126. *
1127. * Default value is false
1128. *
1129. * @access public
1130. * @var mixed
1131. */
1132. var $image_ratio_fill;
1134. /**
1135. * Set this variable to a number of pixels so that {@link image_x} and {@link image_y} are the best match possible
1136. *
1137. * The image will be resized to have approximatively the number of pixels
1138. * The aspect ratio wil be conserved
1139. *
1140. * Default value is false
1141. *
1142. * @access public
1143. * @var mixed
1144. */
1145. var $image_ratio_pixels;
1147. /**
1148. * Set this variable to keep the original size ratio to fit within {@link image_x} x {@link image_y},
1149. * but only if original image is bigger
1150. *
1151. * Default value is false
1152. *
1153. * @access public
1154. * @var bool
1155. */
1156. var $image_ratio_no_zoom_in;
1158. /**
1159. * Set this variable to keep the original size ratio to fit within {@link image_x} x {@link image_y},
1160. * but only if original image is smaller
1161. *
1162. * Default value is false
1163. *
1164. * @access public
1165. * @var bool
1166. */
1167. var $image_ratio_no_zoom_out;
1169. /**
1170. * Set this variable to calculate {@link image_x} automatically , using {@link image_y} and conserving ratio
1171. *
1172. * Default value is false
1173. *
1174. * @access public
1175. * @var bool
1176. */
1177. var $image_ratio_x;
1179. /**
1180. * Set this variable to calculate {@link image_y} automatically , using {@link image_x} and conserving ratio
1181. *
1182. * Default value is false
1183. *
1184. * @access public
1185. * @var bool
1186. */
1187. var $image_ratio_y;
1189. /**
1190. * Set this variable to set a maximum image width, above which the upload will be invalid
1191. *
1192. * Default value is null
1193. *
1194. * @access public
1195. * @var integer
1196. */
1197. var $image_max_width;
1199. /**
1200. * Set this variable to set a maximum image height, above which the upload will be invalid
1201. *
1202. * Default value is null
1203. *
1204. * @access public
1205. * @var integer
1206. */
1207. var $image_max_height;
1209. /**
1210. * Set this variable to set a maximum number of pixels for an image, above which the upload will be invalid
1211. *
1212. * Default value is null
1213. *
1214. * @access public
1215. * @var long
1216. */
1217. var $image_max_pixels;
1219. /**
1220. * Set this variable to set a maximum image aspect ratio, above which the upload will be invalid
1221. *
1222. * Note that ratio = width / height
1223. *
1224. * Default value is null
1225. *
1226. * @access public
1227. * @var float
1228. */
1229. var $image_max_ratio;
1231. /**
1232. * Set this variable to set a minimum image width, below which the upload will be invalid
1233. *
1234. * Default value is null
1235. *
1236. * @access public
1237. * @var integer
1238. */
1239. var $image_min_width;
1241. /**
1242. * Set this variable to set a minimum image height, below which the upload will be invalid
1243. *
1244. * Default value is null
1245. *
1246. * @access public
1247. * @var integer
1248. */
1249. var $image_min_height;
1251. /**
1252. * Set this variable to set a minimum number of pixels for an image, below which the upload will be invalid
1253. *
1254. * Default value is null
1255. *
1256. * @access public
1257. * @var long
1258. */
1259. var $image_min_pixels;
1261. /**
1262. * Set this variable to set a minimum image aspect ratio, below which the upload will be invalid
1263. *
1264. * Note that ratio = width / height
1265. *
1266. * Default value is null
1267. *
1268. * @access public
1269. * @var float
1270. */
1271. var $image_min_ratio;
1273. /**
1274. * Compression level for PNG images
1275. *
1276. * Between 1 (fast but large files) and 9 (slow but smaller files)
1277. *
1278. * Default value is null (Zlib default)
1279. *
1280. * @access public
1281. * @var integer
1282. */
1283. var $png_compression;
1285. /**
1286. * Quality of JPEG created/converted destination image
1287. *
1288. * Default value is 85
1289. *
1290. * @access public
1291. * @var integer
1292. */
1293. var $jpeg_quality;
1295. /**
1296. * Determines the quality of the JPG image to fit a desired file size
1297. *
1298. * The JPG quality will be set between 1 and 100%
1299. * The calculations are approximations.
1300. *
1301. * Value in bytes (integer) or shorthand byte values (string) is allowed.
1302. * The available options are K (for Kilobytes), M (for Megabytes) and G (for Gigabytes)
1303. *
1304. * Default value is null (no calculations)
1305. *
1306. * @access public
1307. * @var integer
1308. */
1309. var $jpeg_size;
1311. /**
1312. * Turns the interlace bit on
1313. *
1314. * This is actually used only for JPEG images, and defaults to false
1315. *
1316. * @access public
1317. * @var boolean
1318. */
1319. var $image_interlace;
1321. /**
1322. * Preserve transparency when resizing or converting an image (deprecated)
1323. *
1324. * Default value is automatically set to true for transparent GIFs
1325. * This setting is now deprecated
1326. *
1327. * @access public
1328. * @var integer
1329. */
1330. var $preserve_transparency;
1332. /**
1333. * Flag set to true when the image is transparent
1334. *
1335. * This is actually used only for transparent GIFs
1336. *
1337. * @access public
1338. * @var boolean
1339. */
1340. var $image_is_transparent;
1342. /**
1343. * Transparent color in a palette
1344. *
1345. * This is actually used only for transparent GIFs
1346. *
1347. * @access public
1348. * @var boolean
1349. */
1350. var $image_transparent_color;
1352. /**
1353. * Background color, used to paint transparent areas with
1354. *
1355. * If set, it will forcibly remove transparency by painting transparent areas with the color
1356. * This setting will fill in all transparent areas in PNG and GIF, as opposed to {@link image_default_color}
1357. * which will do so only in BMP, JPEG, and alpha transparent areas in transparent GIFs
1358. * This setting overrides {@link image_default_color}
1359. *
1360. * Default value is null
1361. *
1362. * @access public
1363. * @var string
1364. */
1365. var $image_background_color;
1367. /**
1368. * Default color for non alpha-transparent images
1369. *
1370. * This setting is to be used to define a background color for semi transparent areas
1371. * of an alpha transparent when the output format doesn't support alpha transparency
1372. * This is useful when, from an alpha transparent PNG image, or an image with alpha transparent features
1373. * if you want to output it as a transparent GIFs for instance, you can set a blending color for transparent areas
1374. * If you output in JPEG or BMP, this color will be used to fill in the previously transparent areas
1375. *
1376. * The default color white
1377. *
1378. * @access public
1379. * @var boolean
1380. */
1381. var $image_default_color;
1383. /**
1384. * Flag set to true when the image is not true color
1385. *
1386. * @access public
1387. * @var boolean
1388. */
1389. var $image_is_palette;
1391. /**
1392. * Corrects the image brightness
1393. *
1394. * Value can range between -127 and 127
1395. *
1396. * Default value is null
1397. *
1398. * @access public
1399. * @var integer
1400. */
1401. var $image_brightness;
1403. /**
1404. * Corrects the image contrast
1405. *
1406. * Value can range between -127 and 127
1407. *
1408. * Default value is null
1409. *
1410. * @access public
1411. * @var integer
1412. */
1413. var $image_contrast;
1415. /**
1416. * Changes the image opacity
1417. *
1418. * Value can range between 0 and 100
1419. *
1420. * Default value is null
1421. *
1422. * @access public
1423. * @var integer
1424. */
1425. var $image_opacity;
1427. /**
1428. * Applies threshold filter
1429. *
1430. * Value can range between -127 and 127
1431. *
1432. * Default value is null
1433. *
1434. * @access public
1435. * @var integer
1436. */
1437. var $image_threshold;
1439. /**
1440. * Applies a tint on the image
1441. *
1442. * Value is an hexadecimal color, such as #FFFFFF
1443. *
1444. * Default value is null
1445. *
1446. * @access public
1447. * @var string;
1448. */
1449. var $image_tint_color;
1451. /**
1452. * Applies a colored overlay on the image
1453. *
1454. * Value is an hexadecimal color, such as #FFFFFF
1455. *
1456. * To use with {@link image_overlay_opacity}
1457. *
1458. * Default value is null
1459. *
1460. * @access public
1461. * @var string;
1462. */
1463. var $image_overlay_color;
1465. /**
1466. * Sets the opacity for the colored overlay
1467. *
1468. * Value is a percentage, as an integer between 0 (transparent) and 100 (opaque)
1469. *
1470. * Unless used with {@link image_overlay_color}, this setting has no effect
1471. *
1472. * Default value is 50
1473. *
1474. * @access public
1475. * @var integer
1476. */
1477. var $image_overlay_opacity;
1479. /**
1480. * Soon to be deprecated old form of {@link image_overlay_opacity}
1481. *
1482. * @access public
1483. * @var integer
1484. */
1485. var $image_overlay_percent;
1487. /**
1488. * Inverts the color of an image
1489. *
1490. * Default value is FALSE
1491. *
1492. * @access public
1493. * @var boolean;
1494. */
1495. var $image_negative;
1497. /**
1498. * Turns the image into greyscale
1499. *
1500. * Default value is FALSE
1501. *
1502. * @access public
1503. * @var boolean;
1504. */
1505. var $image_greyscale;
1507. /**
1508. * Pixelate an image
1509. *
1510. * Value is integer, represents the block size
1511. *
1512. * Default value is null
1513. *
1514. * @access public
1515. * @var integer;
1516. */
1517. var $image_pixelate;
1519. /**
1520. * Applies an unsharp mask, with alpha transparency support
1521. *
1522. * Beware that this unsharp mask is quite resource-intensive
1523. *
1524. * Default value is FALSE
1525. *
1526. * @access public
1527. * @var boolean;
1528. */
1529. var $image_unsharp;
1531. /**
1532. * Sets the unsharp mask amount
1533. *
1534. * Value is an integer between 0 and 500, typically between 50 and 200
1535. *
1536. * Unless used with {@link image_unsharp}, this setting has no effect
1537. *
1538. * Default value is 80
1539. *
1540. * @access public
1541. * @var integer
1542. */
1543. var $image_unsharp_amount;
1545. /**
1546. * Sets the unsharp mask radius
1547. *
1548. * Value is an integer between 0 and 50, typically between 0.5 and 1
1549. * It is not recommended to change it, the default works best
1550. *
1551. * Unless used with {@link image_unsharp}, this setting has no effect
1552. *
1553. * From PHP 5.1, imageconvolution is used, and this setting has no effect
1554. *
1555. * Default value is 0.5
1556. *
1557. * @access public
1558. * @var integer
1559. */
1560. var $image_unsharp_radius;
1562. /**
1563. * Sets the unsharp mask threshold
1564. *
1565. * Value is an integer between 0 and 255, typically between 0 and 5
1566. *
1567. * Unless used with {@link image_unsharp}, this setting has no effect
1568. *
1569. * Default value is 1
1570. *
1571. * @access public
1572. * @var integer
1573. */
1574. var $image_unsharp_threshold;
1576. /**
1577. * Adds a text label on the image
1578. *
1579. * Value is a string, any text. Text will not word-wrap, although you can use breaklines in your text "\n"
1580. *
1581. * If set, this setting allow the use of all other settings starting with image_text_
1582. *
1583. * Replacement tokens can be used in the string:
1584. * <pre>
1585. * gd_version src_name src_name_body src_name_ext
1586. * src_pathname src_mime src_x src_y
1587. * src_type src_bits src_pixels
1588. * src_size src_size_kb src_size_mb src_size_human
1589. * dst_path dst_name_body dst_pathname
1590. * dst_name dst_name_ext dst_x dst_y
1591. * date time host server ip
1592. * </pre>
1593. * The tokens must be enclosed in square brackets: [dst_x] will be replaced by the width of the picture
1594. *
1595. * Default value is null
1596. *
1597. * @access public
1598. * @var string;
1599. */
1600. var $image_text;
1602. /**
1603. * Sets the text direction for the text label
1604. *
1605. * Value is either 'h' or 'v', as in horizontal and vertical
1606. *
1607. * Default value is h (horizontal)
1608. *
1609. * @access public
1610. * @var string;
1611. */
1612. var $image_text_direction;
1614. /**
1615. * Sets the text color for the text label
1616. *
1617. * Value is an hexadecimal color, such as #FFFFFF
1618. *
1619. * Default value is #FFFFFF (white)
1620. *
1621. * @access public
1622. * @var string;
1623. */
1624. var $image_text_color;
1626. /**
1627. * Sets the text opacity in the text label
1628. *
1629. * Value is a percentage, as an integer between 0 (transparent) and 100 (opaque)
1630. *
1631. * Default value is 100
1632. *
1633. * @access public
1634. * @var integer
1635. */
1636. var $image_text_opacity;
1638. /**
1639. * Soon to be deprecated old form of {@link image_text_opacity}
1640. *
1641. * @access public
1642. * @var integer
1643. */
1644. var $image_text_percent;
1646. /**
1647. * Sets the text background color for the text label
1648. *
1649. * Value is an hexadecimal color, such as #FFFFFF
1650. *
1651. * Default value is null (no background)
1652. *
1653. * @access public
1654. * @var string;
1655. */
1656. var $image_text_background;
1658. /**
1659. * Sets the text background opacity in the text label
1660. *
1661. * Value is a percentage, as an integer between 0 (transparent) and 100 (opaque)
1662. *
1663. * Default value is 100
1664. *
1665. * @access public
1666. * @var integer
1667. */
1668. var $image_text_background_opacity;
1670. /**
1671. * Soon to be deprecated old form of {@link image_text_background_opacity}
1672. *
1673. * @access public
1674. * @var integer
1675. */
1676. var $image_text_background_percent;
1678. /**
1679. * Sets the text font in the text label
1680. *
1681. * Value is a an integer between 1 and 5 for GD built-in fonts. 1 is the smallest font, 5 the biggest
1682. * Value can also be a string, which represents the path to a GDF font. The font will be loaded into GD, and used as a built-in font.
1683. *
1684. * Default value is 5
1685. *
1686. * @access public
1687. * @var mixed;
1688. */
1689. var $image_text_font;
1691. /**
1692. * Sets the text label position within the image
1693. *
1694. * Value is one or two out of 'TBLR' (top, bottom, left, right)
1695. *
1696. * The positions are as following:
1697. * <pre>
1698. * TL T TR
1699. * L R
1700. * BL B BR
1701. * </pre>
1702. *
1703. * Default value is null (centered, horizontal and vertical)
1704. *
1705. * Note that is {@link image_text_x} and {@link image_text_y} are used, this setting has no effect
1706. *
1707. * @access public
1708. * @var string;
1709. */
1710. var $image_text_position;
1712. /**
1713. * Sets the text label absolute X position within the image
1714. *
1715. * Value is in pixels, representing the distance between the left of the image and the label
1716. * If a negative value is used, it will represent the distance between the right of the image and the label
1717. *
1718. * Default value is null (so {@link image_text_position} is used)
1719. *
1720. * @access public
1721. * @var integer
1722. */
1723. var $image_text_x;
1725. /**
1726. * Sets the text label absolute Y position within the image
1727. *
1728. * Value is in pixels, representing the distance between the top of the image and the label
1729. * If a negative value is used, it will represent the distance between the bottom of the image and the label
1730. *
1731. * Default value is null (so {@link image_text_position} is used)
1732. *
1733. * @access public
1734. * @var integer
1735. */
1736. var $image_text_y;
1738. /**
1739. * Sets the text label padding
1740. *
1741. * Value is in pixels, representing the distance between the text and the label background border
1742. *
1743. * Default value is 0
1744. *
1745. * This setting can be overriden by {@link image_text_padding_x} and {@link image_text_padding_y}
1746. *
1747. * @access public
1748. * @var integer
1749. */
1750. var $image_text_padding;
1752. /**
1753. * Sets the text label horizontal padding
1754. *
1755. * Value is in pixels, representing the distance between the text and the left and right label background borders
1756. *
1757. * Default value is null
1758. *
1759. * If set, this setting overrides the horizontal part of {@link image_text_padding}
1760. *
1761. * @access public
1762. * @var integer
1763. */
1764. var $image_text_padding_x;
1766. /**
1767. * Sets the text label vertical padding
1768. *
1769. * Value is in pixels, representing the distance between the text and the top and bottom label background borders
1770. *
1771. * Default value is null
1772. *
1773. * If set, his setting overrides the vertical part of {@link image_text_padding}
1774. *
1775. * @access public
1776. * @var integer
1777. */
1778. var $image_text_padding_y;
1780. /**
1781. * Sets the text alignment
1782. *
1783. * Value is a string, which can be either 'L', 'C' or 'R'
1784. *
1785. * Default value is 'C'
1786. *
1787. * This setting is relevant only if the text has several lines.
1788. *
1789. * @access public
1790. * @var string;
1791. */
1792. var $image_text_alignment;
1794. /**
1795. * Sets the text line spacing
1796. *
1797. * Value is an integer, in pixels
1798. *
1799. * Default value is 0
1800. *
1801. * This setting is relevant only if the text has several lines.
1802. *
1803. * @access public
1804. * @var integer
1805. */
1806. var $image_text_line_spacing;
1808. /**
1809. * Sets the height of the reflection
1810. *
1811. * Value is an integer in pixels, or a string which format can be in pixels or percentage.
1812. * For instance, values can be : 40, '40', '40px' or '40%'
1813. *
1814. * Default value is null, no reflection
1815. *
1816. * @access public
1817. * @var mixed;
1818. */
1819. var $image_reflection_height;
1821. /**
1822. * Sets the space between the source image and its relection
1823. *
1824. * Value is an integer in pixels, which can be negative
1825. *
1826. * Default value is 2
1827. *
1828. * This setting is relevant only if {@link image_reflection_height} is set
1829. *
1830. * @access public
1831. * @var integer
1832. */
1833. var $image_reflection_space;
1835. /**
1836. * Sets the color of the reflection background (deprecated)
1837. *
1838. * Value is an hexadecimal color, such as #FFFFFF
1839. *
1840. * Default value is #FFFFFF
1841. *
1842. * This setting is relevant only if {@link image_reflection_height} is set
1843. *
1844. * This setting is now deprecated in favor of {@link image_default_color}
1845. *
1846. * @access public
1847. * @var string;
1848. */
1849. var $image_reflection_color;
1851. /**
1852. * Sets the initial opacity of the reflection
1853. *
1854. * Value is an integer between 0 (no opacity) and 100 (full opacity).
1855. * The reflection will start from {@link image_reflection_opacity} and end up at 0
1856. *
1857. * Default value is 60
1858. *
1859. * This setting is relevant only if {@link image_reflection_height} is set
1860. *
1861. * @access public
1862. * @var integer
1863. */
1864. var $image_reflection_opacity;
1866. /**
1867. * Flips the image vertically or horizontally
1868. *
1869. * Value is either 'h' or 'v', as in horizontal and vertical
1870. *
1871. * Default value is null (no flip)
1872. *
1873. * @access public
1874. * @var string;
1875. */
1876. var $image_flip;
1878. /**
1879. * Rotates the image by increments of 45 degrees
1880. *
1881. * Value is either 90, 180 or 270
1882. *
1883. * Default value is null (no rotation)
1884. *
1885. * @access public
1886. * @var string;
1887. */
1888. var $image_rotate;
1890. /**
1891. * Crops an image
1892. *
1893. * Values are four dimensions, or two, or one (CSS style)
1894. * They represent the amount cropped top, right, bottom and left.
1895. * These values can either be in an array, or a space separated string.
1896. * Each value can be in pixels (with or without 'px'), or percentage (of the source image)
1897. *
1898. * For instance, are valid:
1899. * <pre>
1900. * $foo->image_crop = 20 OR array(20);
1901. * $foo->image_crop = '20px' OR array('20px');
1902. * $foo->image_crop = '20 40' OR array('20', 40);
1903. * $foo->image_crop = '-20 25%' OR array(-20, '25%');
1904. * $foo->image_crop = '20px 25%' OR array('20px', '25%');
1905. * $foo->image_crop = '20% 25%' OR array('20%', '25%');
1906. * $foo->image_crop = '20% 25% 10% 30%' OR array('20%', '25%', '10%', '30%');
1907. * $foo->image_crop = '20px 25px 2px 2px' OR array('20px', '25%px', '2px', '2px');
1908. * $foo->image_crop = '20 25% 40px 10%' OR array(20, '25%', '40px', '10%');
1909. * </pre>
1910. *
1911. * If a value is negative, the image will be expanded, and the extra parts will be filled with black
1912. *
1913. * Default value is null (no cropping)
1914. *
1915. * @access public
1916. * @var string OR array;
1917. */
1918. var $image_crop;
1920. /**
1921. * Crops an image, before an eventual resizing
1922. *
1923. * See {@link image_crop} for valid formats
1924. *
1925. * Default value is null (no cropping)
1926. *
1927. * @access public
1928. * @var string OR array;
1929. */
1930. var $image_precrop;
1932. /**
1933. * Adds a bevel border on the image
1934. *
1935. * Value is a positive integer, representing the thickness of the bevel
1936. *
1937. * If the bevel colors are the same as the background, it makes a fade out effect
1938. *
1939. * Default value is null (no bevel)
1940. *
1941. * @access public
1942. * @var integer
1943. */
1944. var $image_bevel;
1946. /**
1947. * Top and left bevel color
1948. *
1949. * Value is a color, in hexadecimal format
1950. * This setting is used only if {@link image_bevel} is set
1951. *
1952. * Default value is #FFFFFF
1953. *
1954. * @access public
1955. * @var string;
1956. */
1957. var $image_bevel_color1;
1959. /**
1960. * Right and bottom bevel color
1961. *
1962. * Value is a color, in hexadecimal format
1963. * This setting is used only if {@link image_bevel} is set
1964. *
1965. * Default value is #000000
1966. *
1967. * @access public
1968. * @var string;
1969. */
1970. var $image_bevel_color2;
1972. /**
1973. * Adds a single-color border on the outer of the image
1974. *
1975. * Values are four dimensions, or two, or one (CSS style)
1976. * They represent the border thickness top, right, bottom and left.
1977. * These values can either be in an array, or a space separated string.
1978. * Each value can be in pixels (with or without 'px'), or percentage (of the source image)
1979. *
1980. * See {@link image_crop} for valid formats
1981. *
1982. * If a value is negative, the image will be cropped.
1983. * Note that the dimensions of the picture will be increased by the borders' thickness
1984. *
1985. * Default value is null (no border)
1986. *
1987. * @access public
1988. * @var integer
1989. */
1990. var $image_border;
1992. /**
1993. * Border color
1994. *
1995. * Value is a color, in hexadecimal format.
1996. * This setting is used only if {@link image_border} is set
1997. *
1998. * Default value is #FFFFFF
1999. *
2000. * @access public
2001. * @var string;
2002. */
2003. var $image_border_color;
2005. /**
2006. * Sets the opacity for the borders
2007. *
2008. * Value is a percentage, as an integer between 0 (transparent) and 100 (opaque)
2009. *
2010. * Unless used with {@link image_border}, this setting has no effect
2011. *
2012. * Default value is 100
2013. *
2014. * @access public
2015. * @var integer
2016. */
2017. var $image_border_opacity;
2019. /**
2020. * Adds a fading-to-transparent border on the image
2021. *
2022. * Values are four dimensions, or two, or one (CSS style)
2023. * They represent the border thickness top, right, bottom and left.
2024. * These values can either be in an array, or a space separated string.
2025. * Each value can be in pixels (with or without 'px'), or percentage (of the source image)
2026. *
2027. * See {@link image_crop} for valid formats
2028. *
2029. * Note that the dimensions of the picture will not be increased by the borders' thickness
2030. *
2031. * Default value is null (no border)
2032. *
2033. * @access public
2034. * @var integer
2035. */
2036. var $image_border_transparent;
2038. /**
2039. * Adds a multi-color frame on the outer of the image
2040. *
2041. * Value is an integer. Two values are possible for now:
2042. * 1 for flat border, meaning that the frame is mirrored horizontally and vertically
2043. * 2 for crossed border, meaning that the frame will be inversed, as in a bevel effect
2044. *
2045. * The frame will be composed of colored lines set in {@link image_frame_colors}
2046. *
2047. * Note that the dimensions of the picture will be increased by the borders' thickness
2048. *
2049. * Default value is null (no frame)
2050. *
2051. * @access public
2052. * @var integer
2053. */
2054. var $image_frame;
2056. /**
2057. * Sets the colors used to draw a frame
2058. *
2059. * Values is a list of n colors in hexadecimal format.
2060. * These values can either be in an array, or a space separated string.
2061. *
2062. * The colors are listed in the following order: from the outset of the image to its center
2063. *
2064. * For instance, are valid:
2065. * <pre>
2066. * $foo->image_frame_colors = '#FFFFFF #999999 #666666 #000000';
2067. * $foo->image_frame_colors = array('#FFFFFF', '#999999', '#666666', '#000000');
2068. * </pre>
2069. *
2070. * This setting is used only if {@link image_frame} is set
2071. *
2072. * Default value is '#FFFFFF #999999 #666666 #000000'
2073. *
2074. * @access public
2075. * @var string OR array;
2076. */
2077. var $image_frame_colors;
2079. /**
2080. * Sets the opacity for the frame
2081. *
2082. * Value is a percentage, as an integer between 0 (transparent) and 100 (opaque)
2083. *
2084. * Unless used with {@link image_frame}, this setting has no effect
2085. *
2086. * Default value is 100
2087. *
2088. * @access public
2089. * @var integer
2090. */
2091. var $image_frame_opacity;
2093. /**
2094. * Adds a watermark on the image
2095. *
2096. * Value is a local image filename, relative or absolute. GIF, JPG, BMP and PNG are supported, as well as PNG alpha.
2097. *
2098. * If set, this setting allow the use of all other settings starting with image_watermark_
2099. *
2100. * Default value is null
2101. *
2102. * @access public
2103. * @var string;
2104. */
2105. var $image_watermark;
2107. /**
2108. * Sets the watermarkposition within the image
2109. *
2110. * Value is one or two out of 'TBLR' (top, bottom, left, right)
2111. *
2112. * The positions are as following: TL T TR
2113. * L R
2114. * BL B BR
2115. *
2116. * Default value is null (centered, horizontal and vertical)
2117. *
2118. * Note that is {@link image_watermark_x} and {@link image_watermark_y} are used, this setting has no effect
2119. *
2120. * @access public
2121. * @var string;
2122. */
2123. var $image_watermark_position;
2125. /**
2126. * Sets the watermark absolute X position within the image
2127. *
2128. * Value is in pixels, representing the distance between the top of the image and the watermark
2129. * If a negative value is used, it will represent the distance between the bottom of the image and the watermark
2130. *
2131. * Default value is null (so {@link image_watermark_position} is used)
2132. *
2133. * @access public
2134. * @var integer
2135. */
2136. var $image_watermark_x;
2138. /**
2139. * Sets the twatermark absolute Y position within the image
2140. *
2141. * Value is in pixels, representing the distance between the left of the image and the watermark
2142. * If a negative value is used, it will represent the distance between the right of the image and the watermark
2143. *
2144. * Default value is null (so {@link image_watermark_position} is used)
2145. *
2146. * @access public
2147. * @var integer
2148. */
2149. var $image_watermark_y;
2151. /**
2152. * Prevents the watermark to be resized up if it is smaller than the image
2153. *
2154. * If the watermark if smaller than the destination image, taking in account the desired watermark position
2155. * then it will be resized up to fill in the image (minus the {@link image_watermark_x} or {@link image_watermark_y} values)
2156. *
2157. * If you don't want your watermark to be resized in any way, then
2158. * set {@link image_watermark_no_zoom_in} and {@link image_watermark_no_zoom_out} to true
2159. * If you want your watermark to be resized up or doan to fill in the image better, then
2160. * set {@link image_watermark_no_zoom_in} and {@link image_watermark_no_zoom_out} to false
2161. *
2162. * Default value is true (so the watermark will not be resized up, which is the behaviour most people expect)
2163. *
2164. * @access public
2165. * @var integer
2166. */
2167. var $image_watermark_no_zoom_in;
2169. /**
2170. * Prevents the watermark to be resized down if it is bigger than the image
2171. *
2172. * If the watermark if bigger than the destination image, taking in account the desired watermark position
2173. * then it will be resized down to fit in the image (minus the {@link image_watermark_x} or {@link image_watermark_y} values)
2174. *
2175. * If you don't want your watermark to be resized in any way, then
2176. * set {@link image_watermark_no_zoom_in} and {@link image_watermark_no_zoom_out} to true
2177. * If you want your watermark to be resized up or doan to fill in the image better, then
2178. * set {@link image_watermark_no_zoom_in} and {@link image_watermark_no_zoom_out} to false
2179. *
2180. * Default value is false (so the watermark may be shrinked to fit in the image)
2181. *
2182. * @access public
2183. * @var integer
2184. */
2185. var $image_watermark_no_zoom_out;
2187. /**
2188. * List of MIME types per extension
2189. *
2190. * @access private
2191. * @var array
2192. */
2193. var $mime_types;
2195. /**
2196. * Allowed MIME types
2197. *
2198. * Default is a selection of safe mime-types, but you might want to change it
2199. *
2200. * Simple wildcards are allowed, such as image/* or application/*
2201. * If there is only one MIME type allowed, then it can be a string instead of an array
2202. *
2203. * @access public
2204. * @var array OR string
2205. */
2206. var $allowed;
2208. /**
2209. * Forbidden MIME types
2210. *
2211. * Default is a selection of safe mime-types, but you might want to change it
2212. * To only check for forbidden MIME types, and allow everything else, set {@link allowed} to array('* / *') without the spaces
2213. *
2214. * Simple wildcards are allowed, such as image/* or application/*
2215. * If there is only one MIME type forbidden, then it can be a string instead of an array
2216. *
2217. * @access public
2218. * @var array OR string
2219. */
2220. var $forbidden;
2222. /**
2223. * Array of translated error messages
2224. *
2225. * By default, the language is english (en_GB)
2226. * Translations can be in separate files, in a lang/ subdirectory
2227. *
2228. * @access public
2229. * @var array
2230. */
2231. var $translation;
2233. /**
2234. * Language selected for the translations
2235. *
2236. * By default, the language is english ("en_GB")
2237. *
2238. * @access public
2239. * @var array
2240. */
2241. var $language;
2243. /**
2244. * Init or re-init all the processing variables to their default values
2245. *
2246. * This function is called in the constructor, and after each call of {@link process}
2247. *
2248. * @access private
2249. */
2250. function init() {
2252. // overiddable variables
2253. $this->file_new_name_body = null; // replace the name body
2254. $this->file_name_body_add = null; // append to the name body
2255. $this->file_name_body_pre = null; // prepend to the name body
2256. $this->file_new_name_ext = null; // replace the file extension
2257. $this->file_safe_name = true; // format safely the filename
2258. $this->file_force_extension = true; // forces extension if there isn't one
2259. $this->file_overwrite = false; // allows overwritting if the file already exists
2260. $this->file_auto_rename = true; // auto-rename if the file already exists
2261. $this->dir_auto_create = true; // auto-creates directory if missing
2262. $this->dir_auto_chmod = true; // auto-chmod directory if not writeable
2263. $this->dir_chmod = 0777; // default chmod to use
2265. $this->no_script = true; // turns scripts into test files
2266. $this->mime_check = true; // checks the mime type against the allowed list
2268. // these are the different MIME detection methods. if one of these method doesn't work on your
2269. // system, you can deactivate it here; just set it to false
2270. $this->mime_fileinfo = true; // MIME detection with Fileinfo PECL extension
2271. $this->mime_file = true; // MIME detection with UNIX file() command
2272. $this->mime_magic = true; // MIME detection with mime_magic (mime_content_type())
2273. $this->mime_getimagesize = true; // MIME detection with getimagesize()
2275. // get the default max size from php.ini
2276. $this->file_max_size_raw = trim(ini_get('upload_max_filesize'));
2277. $this->file_max_size = $this->getsize($this->file_max_size_raw);
2279. $this->image_resize = false; // resize the image
2280. $this->image_convert = ''; // convert. values :''; 'png'; 'jpeg'; 'gif'; 'bmp'
2282. $this->image_x = 150;
2283. $this->image_y = 150;
2284. $this->image_ratio = false; // keeps aspect ratio with x and y dimensions
2285. $this->image_ratio_crop = false; // keeps aspect ratio with x and y dimensions, filling the space
2286. $this->image_ratio_fill = false; // keeps aspect ratio with x and y dimensions, fitting the image in the space, and coloring the rest
2287. $this->image_ratio_pixels = false; // keeps aspect ratio, calculating x and y so that the image is approx the set number of pixels
2288. $this->image_ratio_no_zoom_in = false;
2289. $this->image_ratio_no_zoom_out = false;
2290. $this->image_ratio_x = false; // calculate the $image_x if true
2291. $this->image_ratio_y = false; // calculate the $image_y if true
2292. $this->png_compression = null;
2293. $this->jpeg_quality = 85;
2294. $this->jpeg_size = null;
2295. $this->image_interlace = false;
2296. $this->preserve_transparency = false;
2297. $this->image_is_transparent = false;
2298. $this->image_transparent_color = null;
2299. $this->image_background_color = null;
2300. $this->image_default_color = '#ffffff';
2301. $this->image_is_palette = false;
2303. $this->image_max_width = null;
2304. $this->image_max_height = null;
2305. $this->image_max_pixels = null;
2306. $this->image_max_ratio = null;
2307. $this->image_min_width = null;
2308. $this->image_min_height = null;
2309. $this->image_min_pixels = null;
2310. $this->image_min_ratio = null;
2312. $this->image_brightness = null;
2313. $this->image_contrast = null;
2314. $this->image_opacity = null;
2315. $this->image_threshold = null;
2316. $this->image_tint_color = null;
2317. $this->image_overlay_color = null;
2318. $this->image_overlay_opacity = null;
2319. $this->image_overlay_percent = null;
2320. $this->image_negative = false;
2321. $this->image_greyscale = false;
2322. $this->image_pixelate = null;
2323. $this->image_unsharp = false;
2324. $this->image_unsharp_amount = 80;
2325. $this->image_unsharp_radius = 0.5;
2326. $this->image_unsharp_threshold = 1;
2328. $this->image_text = null;
2329. $this->image_text_direction = null;
2330. $this->image_text_color = '#FFFFFF';
2331. $this->image_text_opacity = 100;
2332. $this->image_text_percent = 100;
2333. $this->image_text_background = null;
2334. $this->image_text_background_opacity = 100;
2335. $this->image_text_background_percent = 100;
2336. $this->image_text_font = 5;
2337. $this->image_text_x = null;
2338. $this->image_text_y = null;
2339. $this->image_text_position = null;
2340. $this->image_text_padding = 0;
2341. $this->image_text_padding_x = null;
2342. $this->image_text_padding_y = null;
2343. $this->image_text_alignment = 'C';
2344. $this->image_text_line_spacing = 0;
2346. $this->image_reflection_height = null;
2347. $this->image_reflection_space = 2;
2348. $this->image_reflection_color = '#ffffff';
2349. $this->image_reflection_opacity = 60;
2351. $this->image_watermark = null;
2352. $this->image_watermark_x = null;
2353. $this->image_watermark_y = null;
2354. $this->image_watermark_position = null;
2355. $this->image_watermark_no_zoom_in = true;
2356. $this->image_watermark_no_zoom_out = false;
2358. $this->image_flip = null;
2359. $this->image_rotate = null;
2360. $this->image_crop = null;
2361. $this->image_precrop = null;
2363. $this->image_bevel = null;
2364. $this->image_bevel_color1 = '#FFFFFF';
2365. $this->image_bevel_color2 = '#000000';
2366. $this->image_border = null;
2367. $this->image_border_color = '#FFFFFF';
2368. $this->image_border_opacity = 100;
2369. $this->image_border_transparent = null;
2370. $this->image_frame = null;
2371. $this->image_frame_colors = '#FFFFFF #999999 #666666 #000000';
2372. $this->image_frame_opacity = 100;
2374. $this->forbidden = array();
2375. $this->allowed = array(
2376. 'application/arj',
2377. 'application/excel',
2378. 'application/gnutar',
2379. 'application/mspowerpoint',
2380. 'application/msword',
2381. 'application/octet-stream',
2382. 'application/onenote',
2383. 'application/pdf',
2384. 'application/plain',
2385. 'application/postscript',
2386. 'application/powerpoint',
2387. 'application/rar',
2388. 'application/rtf',
2389. 'application/vnd.ms-excel',
2390. 'application/vnd.ms-excel.addin.macroEnabled.12',
2391. 'application/vnd.ms-excel.sheet.binary.macroEnabled.12',
2392. 'application/vnd.ms-excel.sheet.macroEnabled.12',
2393. 'application/vnd.ms-excel.template.macroEnabled.12',
2394. 'application/vnd.ms-office',
2395. 'application/vnd.ms-officetheme',
2396. 'application/vnd.ms-powerpoint',
2397. 'application/vnd.ms-powerpoint.addin.macroEnabled.12',
2398. 'application/vnd.ms-powerpoint.presentation.macroEnabled.12',
2399. 'application/vnd.ms-powerpoint.slide.macroEnabled.12',
2400. 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12',
2401. 'application/vnd.ms-powerpoint.template.macroEnabled.12',
2402. 'application/vnd.ms-word',
2403. 'application/vnd.ms-word.document.macroEnabled.12',
2404. 'application/vnd.ms-word.template.macroEnabled.12',
2405. 'application/vnd.oasis.opendocument.chart',
2406. 'application/vnd.oasis.opendocument.database',
2407. 'application/vnd.oasis.opendocument.formula',
2408. 'application/vnd.oasis.opendocument.graphics',
2409. 'application/vnd.oasis.opendocument.graphics-template',
2410. 'application/vnd.oasis.opendocument.image',
2411. 'application/vnd.oasis.opendocument.presentation',
2412. 'application/vnd.oasis.opendocument.presentation-template',
2413. 'application/vnd.oasis.opendocument.spreadsheet',
2414. 'application/vnd.oasis.opendocument.spreadsheet-template',
2415. 'application/vnd.oasis.opendocument.text',
2416. 'application/vnd.oasis.opendocument.text-master',
2417. 'application/vnd.oasis.opendocument.text-template',
2418. 'application/vnd.oasis.opendocument.text-web',
2419. 'application/vnd.openofficeorg.extension',
2420. 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
2421. 'application/vnd.openxmlformats-officedocument.presentationml.slide',
2422. 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
2423. 'application/vnd.openxmlformats-officedocument.presentationml.template',
2424. 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
2425. 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
2426. 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
2427. 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
2428. 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
2429. 'application/vocaltec-media-file',
2430. 'application/wordperfect',
2431. 'application/x-bittorrent',
2432. 'application/x-bzip',
2433. 'application/x-bzip2',
2434. 'application/x-compressed',
2435. 'application/x-excel',
2436. 'application/x-gzip',
2437. 'application/x-latex',
2438. 'application/x-midi',
2439. 'application/xml',
2440. 'application/x-msexcel',
2441. 'application/x-rar',
2442. 'application/x-rar-compressed',
2443. 'application/x-rtf',
2444. 'application/x-shockwave-flash',
2445. 'application/x-sit',
2446. 'application/x-stuffit',
2447. 'application/x-troff-msvideo',
2448. 'application/x-zip',
2449. 'application/x-zip-compressed',
2450. 'application/zip',
2451. 'audio/*',
2452. 'image/*',
2453. 'multipart/x-gzip',
2454. 'multipart/x-zip',
2455. 'text/plain',
2456. 'text/rtf',
2457. 'text/richtext',
2458. 'text/xml',
2459. 'video/*'
2460. );
2462. $this->mime_types = array(
2463. 'jpg' => 'image/jpeg',
2464. 'jpeg' => 'image/jpeg',
2465. 'jpe' => 'image/jpeg',
2466. 'gif' => 'image/gif',
2467. 'png' => 'image/png',
2468. 'bmp' => 'image/bmp',
2469. 'flv' => 'video/x-flv',
2470. 'js' => 'application/x-javascript',
2471. 'json' => 'application/json',
2472. 'tiff' => 'image/tiff',
2473. 'css' => 'text/css',
2474. 'xml' => 'application/xml',
2475. 'doc' => 'application/msword',
2476. 'docx' => 'application/msword',
2477. 'xls' => 'application/vnd.ms-excel',
2478. 'xlt' => 'application/vnd.ms-excel',
2479. 'xlm' => 'application/vnd.ms-excel',
2480. 'xld' => 'application/vnd.ms-excel',
2481. 'xla' => 'application/vnd.ms-excel',
2482. 'xlc' => 'application/vnd.ms-excel',
2483. 'xlw' => 'application/vnd.ms-excel',
2484. 'xll' => 'application/vnd.ms-excel',
2485. 'ppt' => 'application/vnd.ms-powerpoint',
2486. 'pps' => 'application/vnd.ms-powerpoint',
2487. 'rtf' => 'application/rtf',
2488. 'pdf' => 'application/pdf',
2489. 'html' => 'text/html',
2490. 'htm' => 'text/html',
2491. 'php' => 'text/html',
2492. 'txt' => 'text/plain',
2493. 'mpeg' => 'video/mpeg',
2494. 'mpg' => 'video/mpeg',
2495. 'mpe' => 'video/mpeg',
2496. 'mp3' => 'audio/mpeg3',
2497. 'wav' => 'audio/wav',
2498. 'aiff' => 'audio/aiff',
2499. 'aif' => 'audio/aiff',
2500. 'avi' => 'video/msvideo',
2501. 'wmv' => 'video/x-ms-wmv',
2502. 'mov' => 'video/quicktime',
2503. 'zip' => 'application/zip',
2504. 'tar' => 'application/x-tar',
2505. 'swf' => 'application/x-shockwave-flash',
2506. 'odt' => 'application/vnd.oasis.opendocument.text',
2507. 'ott' => 'application/vnd.oasis.opendocument.text-template',
2508. 'oth' => 'application/vnd.oasis.opendocument.text-web',
2509. 'odm' => 'application/vnd.oasis.opendocument.text-master',
2510. 'odg' => 'application/vnd.oasis.opendocument.graphics',
2511. 'otg' => 'application/vnd.oasis.opendocument.graphics-template',
2512. 'odp' => 'application/vnd.oasis.opendocument.presentation',
2513. 'otp' => 'application/vnd.oasis.opendocument.presentation-template',
2514. 'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
2515. 'ots' => 'application/vnd.oasis.opendocument.spreadsheet-template',
2516. 'odc' => 'application/vnd.oasis.opendocument.chart',
2517. 'odf' => 'application/vnd.oasis.opendocument.formula',
2518. 'odb' => 'application/vnd.oasis.opendocument.database',
2519. 'odi' => 'application/vnd.oasis.opendocument.image',
2520. 'oxt' => 'application/vnd.openofficeorg.extension',
2521. 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
2522. 'docm' => 'application/vnd.ms-word.document.macroEnabled.12',
2523. 'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
2524. 'dotm' => 'application/vnd.ms-word.template.macroEnabled.12',
2525. 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
2526. 'xlsm' => 'application/vnd.ms-excel.sheet.macroEnabled.12',
2527. 'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
2528. 'xltm' => 'application/vnd.ms-excel.template.macroEnabled.12',
2529. 'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12',
2530. 'xlam' => 'application/vnd.ms-excel.addin.macroEnabled.12',
2531. 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
2532. 'pptm' => 'application/vnd.ms-powerpoint.presentation.macroEnabled.12',
2533. 'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
2534. 'ppsm' => 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12',
2535. 'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template',
2536. 'potm' => 'application/vnd.ms-powerpoint.template.macroEnabled.12',
2537. 'ppam' => 'application/vnd.ms-powerpoint.addin.macroEnabled.12',
2538. 'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide',
2539. 'sldm' => 'application/vnd.ms-powerpoint.slide.macroEnabled.12',
2540. 'thmx' => 'application/vnd.ms-officetheme',
2541. 'onetoc' => 'application/onenote',
2542. 'onetoc2' => 'application/onenote',
2543. 'onetmp' => 'application/onenote',
2544. 'onepkg' => 'application/onenote',
2545. );
2547. }
2549. /**
2550. * Constructor. Checks if the file has been uploaded
2551. *
2552. * The constructor takes $_FILES['form_field'] array as argument
2553. * where form_field is the form field name
2554. *
2555. * The constructor will check if the file has been uploaded in its temporary location, and
2556. * accordingly will set {@link uploaded} (and {@link error} is an error occurred)
2557. *
2558. * If the file has been uploaded, the constructor will populate all the variables holding the upload
2559. * information (none of the processing class variables are used here).
2560. * You can have access to information about the file (name, size, MIME type...).
2561. *
2562. *
2563. * Alternatively, you can set the first argument to be a local filename (string)
2564. * This allows processing of a local file, as if the file was uploaded
2565. *
2566. * The optional second argument allows you to set the language for the error messages
2567. *
2568. * @access private
2569. * @param array $file $_FILES['form_field']
2570. * or string $file Local filename
2571. * @param string $lang Optional language code
2572. */
2573. function upload($file, $lang = 'en_GB') {
2575. $this->version = '0.32';
2577. $this->file_src_name = '';
2578. $this->file_src_name_body = '';
2579. $this->file_src_name_ext = '';
2580. $this->file_src_mime = '';
2581. $this->file_src_size = '';
2582. $this->file_src_error = '';
2583. $this->file_src_pathname = '';
2584. $this->file_src_temp = '';
2586. $this->file_dst_path = '';
2587. $this->file_dst_name = '';
2588. $this->file_dst_name_body = '';
2589. $this->file_dst_name_ext = '';
2590. $this->file_dst_pathname = '';
2592. $this->image_src_x = null;
2593. $this->image_src_y = null;
2594. $this->image_src_bits = null;
2595. $this->image_src_type = null;
2596. $this->image_src_pixels = null;
2597. $this->image_dst_x = 0;
2598. $this->image_dst_y = 0;
2600. $this->uploaded = true;
2601. $this->no_upload_check = false;
2602. $this->processed = true;
2603. $this->error = '';
2604. $this->log = '';
2605. $this->allowed = array();
2606. $this->forbidden = array();
2607. $this->file_is_image = false;
2608. $this->init();
2609. $info = null;
2610. $mime_from_browser = null;
2612. // sets default language
2613. $this->translation = array();
2614. $this->translation['file_error'] = 'File error. Please try again.';
2615. $this->translation['local_file_missing'] = 'Local file doesn\'t exist.';
2616. $this->translation['local_file_not_readable'] = 'Local file is not readable.';
2617. $this->translation['uploaded_too_big_ini'] = 'File upload error (the uploaded file exceeds the upload_max_filesize directive in php.ini).';
2618. $this->translation['uploaded_too_big_html'] = 'File upload error (the uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the html form).';
2619. $this->translation['uploaded_partial'] = 'File upload error (the uploaded file was only partially uploaded).';
2620. $this->translation['uploaded_missing'] = 'File upload error (no file was uploaded).';
2621. $this->translation['uploaded_no_tmp_dir'] = 'File upload error (missing a temporary folder).';
2622. $this->translation['uploaded_cant_write'] = 'File upload error (failed to write file to disk).';
2623. $this->translation['uploaded_err_extension'] = 'File upload error (file upload stopped by extension).';
2624. $this->translation['uploaded_unknown'] = 'File upload error (unknown error code).';
2625. $this->translation['try_again'] = 'File upload error. Please try again.';
2626. $this->translation['file_too_big'] = 'File too big.';
2627. $this->translation['no_mime'] = 'MIME type can\'t be detected.';
2628. $this->translation['incorrect_file'] = 'Incorrect type of file.';
2629. $this->translation['image_too_wide'] = 'Image too wide.';
2630. $this->translation['image_too_narrow'] = 'Image too narrow.';
2631. $this->translation['image_too_high'] = 'Image too tall.';
2632. $this->translation['image_too_short'] = 'Image too short.';
2633. $this->translation['ratio_too_high'] = 'Image ratio too high (image too wide).';
2634. $this->translation['ratio_too_low'] = 'Image ratio too low (image too high).';
2635. $this->translation['too_many_pixels'] = 'Image has too many pixels.';
2636. $this->translation['not_enough_pixels'] = 'Image has not enough pixels.';
2637. $this->translation['file_not_uploaded'] = 'File not uploaded. Can\'t carry on a process.';
2638. $this->translation['already_exists'] = '%s already exists. Please change the file name.';
2639. $this->translation['temp_file_missing'] = 'No correct temp source file. Can\'t carry on a process.';
2640. $this->translation['source_missing'] = 'No correct uploaded source file. Can\'t carry on a process.';
2641. $this->translation['destination_dir'] = 'Destination directory can\'t be created. Can\'t carry on a process.';
2642. $this->translation['destination_dir_missing'] = 'Destination directory doesn\'t exist. Can\'t carry on a process.';
2643. $this->translation['destination_path_not_dir'] = 'Destination path is not a directory. Can\'t carry on a process.';
2644. $this->translation['destination_dir_write'] = 'Destination directory can\'t be made writeable. Can\'t carry on a process.';
2645. $this->translation['destination_path_write'] = 'Destination path is not a writeable. Can\'t carry on a process.';
2646. $this->translation['temp_file'] = 'Can\'t create the temporary file. Can\'t carry on a process.';
2647. $this->translation['source_not_readable'] = 'Source file is not readable. Can\'t carry on a process.';
2648. $this->translation['no_create_support'] = 'No create from %s support.';
2649. $this->translation['create_error'] = 'Error in creating %s image from source.';
2650. $this->translation['source_invalid'] = 'Can\'t read image source. Not an image?.';
2651. $this->translation['gd_missing'] = 'GD doesn\'t seem to be present.';
2652. $this->translation['watermark_no_create_support'] = 'No create from %s support, can\'t read watermark.';
2653. $this->translation['watermark_create_error'] = 'No %s read support, can\'t create watermark.';
2654. $this->translation['watermark_invalid'] = 'Unknown image format, can\'t read watermark.';
2655. $this->translation['file_create'] = 'No %s create support.';
2656. $this->translation['no_conversion_type'] = 'No conversion type defined.';
2657. $this->translation['copy_failed'] = 'Error copying file on the server. copy() failed.';
2658. $this->translation['reading_failed'] = 'Error reading the file.';
2660. // determines the language
2661. $this->lang = $lang;
2662. if ($this->lang != 'en_GB' && file_exists(dirname(__FILE__).'/lang') && file_exists(dirname(__FILE__).'/lang/class.upload.' . $lang . '.php')) {
2663. $translation = null;
2664. include(dirname(__FILE__).'/lang/class.upload.' . $lang . '.php');
2665. if (is_array($translation)) {
2666. $this->translation = array_merge($this->translation, $translation);
2667. } else {
2668. $this->lang = 'en_GB';
2669. }
2670. }
2673. // determines the supported MIME types, and matching image format
2674. $this->image_supported = array();
2675. if ($this->gdversion()) {
2676. if (imagetypes() & IMG_GIF) {
2677. $this->image_supported['image/gif'] = 'gif';
2678. }
2679. if (imagetypes() & IMG_JPG) {
2680. $this->image_supported['image/jpg'] = 'jpg';
2681. $this->image_supported['image/jpeg'] = 'jpg';
2682. $this->image_supported['image/pjpeg'] = 'jpg';
2683. }
2684. if (imagetypes() & IMG_PNG) {
2685. $this->image_supported['image/png'] = 'png';
2686. $this->image_supported['image/x-png'] = 'png';
2687. }
2688. if (imagetypes() & IMG_WBMP) {
2689. $this->image_supported['image/bmp'] = 'bmp';
2690. $this->image_supported['image/x-ms-bmp'] = 'bmp';
2691. $this->image_supported['image/x-windows-bmp'] = 'bmp';
2692. }
2693. }
2695. // display some system information
2696. if (empty($this->log)) {
2697. $this->log .= '<b>system information</b><br />';
2698. if (function_exists('ini_get_all')) {
2699. $inis = ini_get_all();
2700. $open_basedir = (array_key_exists('open_basedir', $inis) && array_key_exists('local_value', $inis['open_basedir']) && !empty($inis['open_basedir']['local_value'])) ? $inis['open_basedir']['local_value'] : false;
2701. } else {
2702. $open_basedir = false;
2703. }
2704. $gd = $this->gdversion() ? $this->gdversion(true) : 'GD not present';
2705. $supported = trim((in_array('png', $this->image_supported) ? 'png' : '') . ' ' . (in_array('jpg', $this->image_supported) ? 'jpg' : '') . ' ' . (in_array('gif', $this->image_supported) ? 'gif' : '') . ' ' . (in_array('bmp', $this->image_supported) ? 'bmp' : ''));
2706. $this->log .= '-&nbsp;class version : ' . $this->version . '<br />';
2707. $this->log .= '-&nbsp;operating system : ' . PHP_OS . '<br />';
2708. $this->log .= '-&nbsp;PHP version : ' . PHP_VERSION . '<br />';
2709. $this->log .= '-&nbsp;GD version : ' . $gd . '<br />';
2710. $this->log .= '-&nbsp;supported image types : ' . (!empty($supported) ? $supported : 'none') . '<br />';
2711. $this->log .= '-&nbsp;open_basedir : ' . (!empty($open_basedir) ? $open_basedir : 'no restriction') . '<br />';
2712. $this->log .= '-&nbsp;upload_max_filesize : ' . $this->file_max_size_raw . ' (' . $this->file_max_size . ' bytes)<br />';
2713. $this->log .= '-&nbsp;language : ' . $this->lang . '<br />';
2714. }
2716. if (!$file) {
2717. $this->uploaded = false;
2718. $this->error = $this->translate('file_error');
2719. }
2721. // check if we sent a local filename or a PHP stream rather than a $_FILE element
2722. if (!is_array($file)) {
2723. if (empty($file)) {
2724. $this->uploaded = false;
2725. $this->error = $this->translate('file_error');
2726. } else {
2727. if (substr($file, 0, 4) == 'php:') {
2728. // this is a local filename, i.e.not uploaded
2729. $file = preg_replace('/^php:(.*)/i', '$1', $file);
2730. if (!$file) $file = $_SERVER['HTTP_X_FILE_NAME'];
2731. if (!$file) $file = 'unknown';
2732. $this->log .= '<b>' . $this->translate("source is a PHP stream") . ' ' . $file . '</b><br />';
2733. $this->no_upload_check = TRUE;
2735. $this->log .= '- this is a PHP stream, requires a temp file ... ';
2736. $hash = $this->temp_dir() . md5($file . rand(1, 1000));
2737. if (file_put_contents($hash, file_get_contents('php://input'))) {
2738. $this->file_src_pathname = $hash;
2739. $this->log .= ' file created<br />';
2740. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;temp file is: ' . $this->file_src_pathname . '<br />';
2741. } else {
2742. $this->log .= ' failed<br />';
2743. $this->uploaded = false;
2744. $this->error = $this->translate('temp_file');
2745. }
2747. if ($this->uploaded) {
2748. $this->file_src_name = $file;
2749. $this->log .= '- local file OK<br />';
2750. preg_match('/\.([^\.]*$)/', $this->file_src_name, $extension);
2751. if (is_array($extension) && sizeof($extension) > 0) {
2752. $this->file_src_name_ext = strtolower($extension[1]);
2753. $this->file_src_name_body = substr($this->file_src_name, 0, ((strlen($this->file_src_name) - strlen($this->file_src_name_ext)))-1);
2754. } else {
2755. $this->file_src_name_ext = '';
2756. $this->file_src_name_body = $this->file_src_name;
2757. }
2758. $this->file_src_size = (file_exists($file) ? filesize($file) : 0);
2759. }
2760. $this->file_src_error = 0;
2762. } else {
2763. // this is a local filename, i.e.not uploaded
2764. $this->log .= '<b>' . $this->translate("source is a local file") . ' ' . $file . '</b><br />';
2765. $this->no_upload_check = TRUE;
2767. if ($this->uploaded && !file_exists($file)) {
2768. $this->uploaded = false;
2769. $this->error = $this->translate('local_file_missing');
2770. }
2772. if ($this->uploaded && !is_readable($file)) {
2773. $this->uploaded = false;
2774. $this->error = $this->translate('local_file_not_readable');
2775. }
2777. if ($this->uploaded) {
2778. $this->file_src_pathname = $file;
2779. $this->file_src_name = basename($file);
2780. $this->log .= '- local file OK<br />';
2781. preg_match('/\.([^\.]*$)/', $this->file_src_name, $extension);
2782. if (is_array($extension) && sizeof($extension) > 0) {
2783. $this->file_src_name_ext = strtolower($extension[1]);
2784. $this->file_src_name_body = substr($this->file_src_name, 0, ((strlen($this->file_src_name) - strlen($this->file_src_name_ext)))-1);
2785. } else {
2786. $this->file_src_name_ext = '';
2787. $this->file_src_name_body = $this->file_src_name;
2788. }
2789. $this->file_src_size = (file_exists($file) ? filesize($file) : 0);
2790. }
2791. $this->file_src_error = 0;
2792. }
2793. }
2794. } else {
2795. // this is an element from $_FILE, i.e. an uploaded file
2796. $this->log .= '<b>source is an uploaded file</b><br />';
2797. if ($this->uploaded) {
2798. $this->file_src_error = trim($file['error']);
2799. switch($this->file_src_error) {
2800. case UPLOAD_ERR_OK:
2801. // all is OK
2802. $this->log .= '- upload OK<br />';
2803. break;
2804. case UPLOAD_ERR_INI_SIZE:
2805. $this->uploaded = false;
2806. $this->error = $this->translate('uploaded_too_big_ini');
2807. break;
2808. case UPLOAD_ERR_FORM_SIZE:
2809. $this->uploaded = false;
2810. $this->error = $this->translate('uploaded_too_big_html');
2811. break;
2812. case UPLOAD_ERR_PARTIAL:
2813. $this->uploaded = false;
2814. $this->error = $this->translate('uploaded_partial');
2815. break;
2816. case UPLOAD_ERR_NO_FILE:
2817. $this->uploaded = false;
2818. $this->error = $this->translate('uploaded_missing');
2819. break;
2820. case @UPLOAD_ERR_NO_TMP_DIR:
2821. $this->uploaded = false;
2822. $this->error = $this->translate('uploaded_no_tmp_dir');
2823. break;
2824. case @UPLOAD_ERR_CANT_WRITE:
2825. $this->uploaded = false;
2826. $this->error = $this->translate('uploaded_cant_write');
2827. break;
2828. case @UPLOAD_ERR_EXTENSION:
2829. $this->uploaded = false;
2830. $this->error = $this->translate('uploaded_err_extension');
2831. break;
2832. default:
2833. $this->uploaded = false;
2834. $this->error = $this->translate('uploaded_unknown') . ' ('.$this->file_src_error.')';
2835. }
2836. }
2838. if ($this->uploaded) {
2839. $this->file_src_pathname = $file['tmp_name'];
2840. $this->file_src_name = $file['name'];
2841. if ($this->file_src_name == '') {
2842. $this->uploaded = false;
2843. $this->error = $this->translate('try_again');
2844. }
2845. }
2847. if ($this->uploaded) {
2848. $this->log .= '- file name OK<br />';
2849. preg_match('/\.([^\.]*$)/', $this->file_src_name, $extension);
2850. if (is_array($extension) && sizeof($extension) > 0) {
2851. $this->file_src_name_ext = strtolower($extension[1]);
2852. $this->file_src_name_body = substr($this->file_src_name, 0, ((strlen($this->file_src_name) - strlen($this->file_src_name_ext)))-1);
2853. } else {
2854. $this->file_src_name_ext = '';
2855. $this->file_src_name_body = $this->file_src_name;
2856. }
2857. $this->file_src_size = $file['size'];
2858. $mime_from_browser = $file['type'];
2859. }
2860. }
2862. if ($this->uploaded) {
2863. $this->log .= '<b>determining MIME type</b><br />';
2864. $this->file_src_mime = null;
2866. // checks MIME type with Fileinfo PECL extension
2867. if (!$this->file_src_mime || !is_string($this->file_src_mime) || empty($this->file_src_mime) || strpos($this->file_src_mime, '/') === FALSE) {
2868. if ($this->mime_fileinfo) {
2869. $this->log .= '- Checking MIME type with Fileinfo PECL extension<br />';
2870. if (function_exists('finfo_open')) {
2871. $path = null;
2872. if ($this->mime_fileinfo !== '') {
2873. if ($this->mime_fileinfo === true) {
2874. if (getenv('MAGIC') === FALSE) {
2875. if (substr(PHP_OS, 0, 3) == 'WIN') {
2876. $path = realpath(ini_get('extension_dir') . '/../') . 'extras/magic';
2877. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;MAGIC path defaults to ' . $path . '<br />';
2878. }
2879. } else {
2880. $path = getenv('MAGIC');
2881. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;MAGIC path is set to ' . $path . ' from MAGIC variable<br />';
2882. }
2883. } else {
2884. $path = $this->mime_fileinfo;
2885. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;MAGIC path is set to ' . $path . '<br />';
2886. }
2887. }
2888. if ($path) {
2889. $f = @finfo_open(FILEINFO_MIME, $path);
2890. } else {
2891. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;MAGIC path will not be used<br />';
2892. $f = @finfo_open(FILEINFO_MIME);
2893. }
2894. if (is_resource($f)) {
2895. $mime = finfo_file($f, realpath($this->file_src_pathname));
2896. finfo_close($f);
2897. $this->file_src_mime = $mime;
2898. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;MIME type detected as ' . $this->file_src_mime . ' by Fileinfo PECL extension<br />';
2899. if (preg_match("/^([\.-\w]+)\/([\.-\w]+)(.*)$/i", $this->file_src_mime)) {
2900. $this->file_src_mime = preg_replace("/^([\.-\w]+)\/([\.-\w]+)(.*)$/i", '$1/$2', $this->file_src_mime);
2901. $this->log .= '-&nbsp;MIME validated as ' . $this->file_src_mime . '<br />';
2902. } else {
2903. $this->file_src_mime = null;
2904. }
2905. } else {
2906. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;Fileinfo PECL extension failed (finfo_open)<br />';
2907. }
2908. } elseif (@class_exists('finfo')) {
2909. $f = new finfo( FILEINFO_MIME );
2910. if ($f) {
2911. $this->file_src_mime = $f->file(realpath($this->file_src_pathname));
2912. $this->log .= '- MIME type detected as ' . $this->file_src_mime . ' by Fileinfo PECL extension<br />';
2913. if (preg_match("/^([\.-\w]+)\/([\.-\w]+)(.*)$/i", $this->file_src_mime)) {
2914. $this->file_src_mime = preg_replace("/^([\.-\w]+)\/([\.-\w]+)(.*)$/i", '$1/$2', $this->file_src_mime);
2915. $this->log .= '-&nbsp;MIME validated as ' . $this->file_src_mime . '<br />';
2916. } else {
2917. $this->file_src_mime = null;
2918. }
2919. } else {
2920. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;Fileinfo PECL extension failed (finfo)<br />';
2921. }
2922. } else {
2923. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;Fileinfo PECL extension not available<br />';
2924. }
2925. } else {
2926. $this->log .= '- Fileinfo PECL extension deactivated<br />';
2927. }
2928. }
2930. // checks MIME type with shell if unix access is authorized
2931. if (!$this->file_src_mime || !is_string($this->file_src_mime) || empty($this->file_src_mime) || strpos($this->file_src_mime, '/') === FALSE) {
2932. if ($this->mime_file) {
2933. $this->log .= '- Checking MIME type with UNIX file() command<br />';
2934. if (substr(PHP_OS, 0, 3) != 'WIN') {
2935. if (function_exists('exec') && function_exists('escapeshellarg') && !extension_loaded('suhosin')) {
2936. if (strlen($mime = @exec("file -bi ".escapeshellarg($this->file_src_pathname))) != 0) {
2937. $this->file_src_mime = trim($mime);
2938. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;MIME type detected as ' . $this->file_src_mime . ' by UNIX file() command<br />';
2939. if (preg_match("/^([\.-\w]+)\/([\.-\w]+)(.*)$/i", $this->file_src_mime)) {
2940. $this->file_src_mime = preg_replace("/^([\.-\w]+)\/([\.-\w]+)(.*)$/i", '$1/$2', $this->file_src_mime);
2941. $this->log .= '-&nbsp;MIME validated as ' . $this->file_src_mime . '<br />';
2942. } else {
2943. $this->file_src_mime = null;
2944. }
2945. } else {
2946. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;UNIX file() command failed<br />';
2947. }
2948. } else {
2949. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;PHP exec() function is disabled<br />';
2950. }
2951. } else {
2952. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;UNIX file() command not availabled<br />';
2953. }
2954. } else {
2955. $this->log .= '- UNIX file() command is deactivated<br />';
2956. }
2957. }
2959. // checks MIME type with mime_magic
2960. if (!$this->file_src_mime || !is_string($this->file_src_mime) || empty($this->file_src_mime) || strpos($this->file_src_mime, '/') === FALSE) {
2961. if ($this->mime_magic) {
2962. $this->log .= '- Checking MIME type with mime.magic file (mime_content_type())<br />';
2963. if (function_exists('mime_content_type')) {
2964. $this->file_src_mime = mime_content_type($this->file_src_pathname);
2965. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;MIME type detected as ' . $this->file_src_mime . ' by mime_content_type()<br />';
2966. if (preg_match("/^([\.-\w]+)\/([\.-\w]+)(.*)$/i", $this->file_src_mime)) {
2967. $this->file_src_mime = preg_replace("/^([\.-\w]+)\/([\.-\w]+)(.*)$/i", '$1/$2', $this->file_src_mime);
2968. $this->log .= '-&nbsp;MIME validated as ' . $this->file_src_mime . '<br />';
2969. } else {
2970. $this->file_src_mime = null;
2971. }
2972. } else {
2973. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;mime_content_type() is not available<br />';
2974. }
2975. } else {
2976. $this->log .= '- mime.magic file (mime_content_type()) is deactivated<br />';
2977. }
2978. }
2980. // checks MIME type with getimagesize()
2981. if (!$this->file_src_mime || !is_string($this->file_src_mime) || empty($this->file_src_mime) || strpos($this->file_src_mime, '/') === FALSE) {
2982. if ($this->mime_getimagesize) {
2983. $this->log .= '- Checking MIME type with getimagesize()<br />';
2984. $info = getimagesize($this->file_src_pathname);
2985. if (is_array($info) && array_key_exists('mime', $info)) {
2986. $this->file_src_mime = trim($info['mime']);
2987. if (empty($this->file_src_mime)) {
2988. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;MIME empty, guessing from type<br />';
2989. $mime = (is_array($info) && array_key_exists(2, $info) ? $info[2] : null); // 1 = GIF, 2 = JPG, 3 = PNG
2990. $this->file_src_mime = ($mime==IMAGETYPE_GIF ? 'image/gif' : ($mime==IMAGETYPE_JPEG ? 'image/jpeg' : ($mime==IMAGETYPE_PNG ? 'image/png' : ($mime==IMAGETYPE_BMP ? 'image/bmp' : null))));
2991. }
2992. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;MIME type detected as ' . $this->file_src_mime . ' by PHP getimagesize() function<br />';
2993. if (preg_match("/^([\.-\w]+)\/([\.-\w]+)(.*)$/i", $this->file_src_mime)) {
2994. $this->file_src_mime = preg_replace("/^([\.-\w]+)\/([\.-\w]+)(.*)$/i", '$1/$2', $this->file_src_mime);
2995. $this->log .= '-&nbsp;MIME validated as ' . $this->file_src_mime . '<br />';
2996. } else {
2997. $this->file_src_mime = null;
2998. }
2999. } else {
3000. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;getimagesize() failed<br />';
3001. }
3002. } else {
3003. $this->log .= '- getimagesize() is deactivated<br />';
3004. }
3005. }
3007. // default to MIME from browser (or Flash)
3008. if (!empty($mime_from_browser) && !$this->file_src_mime || !is_string($this->file_src_mime) || empty($this->file_src_mime)) {
3009. $this->file_src_mime =$mime_from_browser;
3010. $this->log .= '- MIME type detected as ' . $this->file_src_mime . ' by browser<br />';
3011. if (preg_match("/^([\.-\w]+)\/([\.-\w]+)(.*)$/i", $this->file_src_mime)) {
3012. $this->file_src_mime = preg_replace("/^([\.-\w]+)\/([\.-\w]+)(.*)$/i", '$1/$2', $this->file_src_mime);
3013. $this->log .= '-&nbsp;MIME validated as ' . $this->file_src_mime . '<br />';
3014. } else {
3015. $this->file_src_mime = null;
3016. }
3017. }
3019. // we need to work some magic if we upload via Flash
3020. if ($this->file_src_mime == 'application/octet-stream' || !$this->file_src_mime || !is_string($this->file_src_mime) || empty($this->file_src_mime) || strpos($this->file_src_mime, '/') === FALSE) {
3021. if ($this->file_src_mime == 'application/octet-stream') $this->log .= '- Flash may be rewriting MIME as application/octet-stream<br />';
3022. $this->log .= '- Try to guess MIME type from file extension (' . $this->file_src_name_ext . '): ';
3023. if (array_key_exists($this->file_src_name_ext, $this->mime_types)) $this->file_src_mime = $this->mime_types[$this->file_src_name_ext];
3024. if ($this->file_src_mime == 'application/octet-stream') {
3025. $this->log .= 'doesn\'t look like anything known<br />';
3026. } else {
3027. $this->log .= 'MIME type set to ' . $this->file_src_mime . '<br />';
3028. }
3029. }
3031. if (!$this->file_src_mime || !is_string($this->file_src_mime) || empty($this->file_src_mime) || strpos($this->file_src_mime, '/') === FALSE) {
3032. $this->log .= '- MIME type couldn\'t be detected! (' . (string) $this->file_src_mime . ')<br />';
3033. }
3035. // determine whether the file is an image
3036. if ($this->file_src_mime && is_string($this->file_src_mime) && !empty($this->file_src_mime) && array_key_exists($this->file_src_mime, $this->image_supported)) {
3037. $this->file_is_image = true;
3038. $this->image_src_type = $this->image_supported[$this->file_src_mime];
3039. }
3041. // if the file is an image, we gather some useful data
3042. if ($this->file_is_image) {
3043. if ($h = fopen($this->file_src_pathname, 'r')) {
3044. fclose($h);
3045. $info = getimagesize($this->file_src_pathname);
3046. if (is_array($info)) {
3047. $this->image_src_x = $info[0];
3048. $this->image_src_y = $info[1];
3049. $this->image_dst_x = $this->image_src_x;
3050. $this->image_dst_y = $this->image_src_y;
3051. $this->image_src_pixels = $this->image_src_x * $this->image_src_y;
3052. $this->image_src_bits = array_key_exists('bits', $info) ? $info['bits'] : null;
3053. } else {
3054. $this->file_is_image = false;
3055. $this->uploaded = false;
3056. $this->log .= '- can\'t retrieve image information, image may have been tampered with<br />';
3057. $this->error = $this->translate('source_invalid');
3058. }
3059. } else {
3060. $this->log .= '- can\'t read source file directly. open_basedir restriction in place?<br />';
3061. }
3062. }
3064. $this->log .= '<b>source variables</b><br />';
3065. $this->log .= '- You can use all these before calling process()<br />';
3066. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;file_src_name : ' . $this->file_src_name . '<br />';
3067. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;file_src_name_body : ' . $this->file_src_name_body . '<br />';
3068. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;file_src_name_ext : ' . $this->file_src_name_ext . '<br />';
3069. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;file_src_pathname : ' . $this->file_src_pathname . '<br />';
3070. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;file_src_mime : ' . $this->file_src_mime . '<br />';
3071. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;file_src_size : ' . $this->file_src_size . ' (max= ' . $this->file_max_size . ')<br />';
3072. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;file_src_error : ' . $this->file_src_error . '<br />';
3074. if ($this->file_is_image) {
3075. $this->log .= '- source file is an image<br />';
3076. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;image_src_x : ' . $this->image_src_x . '<br />';
3077. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;image_src_y : ' . $this->image_src_y . '<br />';
3078. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;image_src_pixels : ' . $this->image_src_pixels . '<br />';
3079. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;image_src_type : ' . $this->image_src_type . '<br />';
3080. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;image_src_bits : ' . $this->image_src_bits . '<br />';
3081. }
3082. }
3084. }
3086. /**
3087. * Returns the version of GD
3088. *
3089. * @access public
3090. * @param boolean $full Optional flag to get precise version
3091. * @return float GD version
3092. */
3093. function gdversion($full = false) {
3094. static $gd_version = null;
3095. static $gd_full_version = null;
3096. if ($gd_version === null) {
3097. if (function_exists('gd_info')) {
3098. $gd = gd_info();
3099. $gd = $gd["GD Version"];
3100. $regex = "/([\d\.]+)/i";
3101. } else {
3102. ob_start();
3103. phpinfo(8);
3104. $gd = ob_get_contents();
3105. ob_end_clean();
3106. $regex = "/\bgd\s+version\b[^\d\n\r]+?([\d\.]+)/i";
3107. }
3108. if (preg_match($regex, $gd, $m)) {
3109. $gd_full_version = (string) $m[1];
3110. $gd_version = (float) $m[1];
3111. } else {
3112. $gd_full_version = 'none';
3113. $gd_version = 0;
3114. }
3115. }
3116. if ($full) {
3117. return $gd_full_version;
3118. } else {
3119. return $gd_version;
3120. }
3121. }
3123. /**
3124. * Creates directories recursively
3125. *
3126. * @access private
3127. * @param string $path Path to create
3128. * @param integer $mode Optional permissions
3129. * @return boolean Success
3130. */
3131. function rmkdir($path, $mode = 0777) {
3132. return is_dir($path) || ( $this->rmkdir(dirname($path), $mode) && $this->_mkdir($path, $mode) );
3133. }
3135. /**
3136. * Creates directory
3137. *
3138. * @access private
3139. * @param string $path Path to create
3140. * @param integer $mode Optional permissions
3141. * @return boolean Success
3142. */
3143. function _mkdir($path, $mode = 0777) {
3144. $old = umask(0);
3145. $res = @mkdir($path, $mode);
3146. umask($old);
3147. return $res;
3148. }
3150. /**
3151. * Translate error messages
3152. *
3153. * @access private
3154. * @param string $str Message to translate
3155. * @param array $tokens Optional token values
3156. * @return string Translated string
3157. */
3158. function translate($str, $tokens = array()) {
3159. if (array_key_exists($str, $this->translation)) $str = $this->translation[$str];
3160. if (is_array($tokens) && sizeof($tokens) > 0) $str = vsprintf($str, $tokens);
3161. return $str;
3162. }
3164. /**
3165. * Returns the temp directory
3166. *
3167. * @access private
3168. * @return string Temp directory string
3169. */
3170. function temp_dir() {
3171. $dir = '';
3172. if (function_exists('sys_get_temp_dir')) $dir = sys_get_temp_dir();
3173. if (!$dir && $tmp=getenv('TMP')) $dir = $tmp;
3174. if (!$dir && $tmp=getenv('TEMP')) $dir = $tmp;
3175. if (!$dir && $tmp=getenv('TMPDIR')) $dir = $tmp;
3176. if (!$dir) {
3177. $tmp = tempnam(__FILE__,'');
3178. if (file_exists($tmp)) {
3179. unlink($tmp);
3180. $dir = dirname($tmp);
3181. }
3182. }
3183. if (!$dir) return '';
3184. $slash = (strtolower(substr(PHP_OS, 0, 3)) === 'win' ? '\\' : '/');
3185. if (substr($dir, -1) != $slash) $dir = $dir . $slash;
3186. return $dir;
3187. }
3189. /**
3190. * Decodes colors
3191. *
3192. * @access private
3193. * @param string $color Color string
3194. * @return array RGB colors
3195. */
3196. function getcolors($color) {
3197. $color = str_replace('#', '', $color);
3198. if (strlen($color) == 3) $color = str_repeat(substr($color, 0, 1), 2) . str_repeat(substr($color, 1, 1), 2) . str_repeat(substr($color, 2, 1), 2);
3199. $r = sscanf($color, "%2x%2x%2x");
3200. $red = (is_array($r) && array_key_exists(0, $r) && is_numeric($r[0]) ? $r[0] : 0);
3201. $green = (is_array($r) && array_key_exists(1, $r) && is_numeric($r[1]) ? $r[1] : 0);
3202. $blue = (is_array($r) && array_key_exists(2, $r) && is_numeric($r[2]) ? $r[2] : 0);
3203. return array($red, $green, $blue);
3204. }
3206. /**
3207. * Decodes sizes
3208. *
3209. * @access private
3210. * @param string $size Size in bytes, or shorthand byte options
3211. * @return integer Size in bytes
3212. */
3213. function getsize($size) {
3214. $last = strtolower($size{strlen($size)-1});
3215. switch($last) {
3216. case 'g':
3217. $size *= 1024;
3218. case 'm':
3219. $size *= 1024;
3220. case 'k':
3221. $size *= 1024;
3222. }
3223. return $size;
3224. }
3226. /**
3227. * Decodes offsets
3228. *
3229. * @access private
3230. * @param misc $offsets Offsets, as an integer, a string or an array
3231. * @param integer $x Reference picture width
3232. * @param integer $y Reference picture height
3233. * @param boolean $round Round offsets before returning them
3234. * @param boolean $negative Allow negative offsets to be returned
3235. * @return array Array of four offsets (TRBL)
3236. */
3237. function getoffsets($offsets, $x, $y, $round = true, $negative = true) {
3238. if (!is_array($offsets)) $offsets = explode(' ', $offsets);
3239. if (sizeof($offsets) == 4) {
3240. $ct = $offsets[0]; $cr = $offsets[1]; $cb = $offsets[2]; $cl = $offsets[3];
3241. } else if (sizeof($offsets) == 2) {
3242. $ct = $offsets[0]; $cr = $offsets[1]; $cb = $offsets[0]; $cl = $offsets[1];
3243. } else {
3244. $ct = $offsets[0]; $cr = $offsets[0]; $cb = $offsets[0]; $cl = $offsets[0];
3245. }
3246. if (strpos($ct, '%')>0) $ct = $y * (str_replace('%','',$ct) / 100);
3247. if (strpos($cr, '%')>0) $cr = $x * (str_replace('%','',$cr) / 100);
3248. if (strpos($cb, '%')>0) $cb = $y * (str_replace('%','',$cb) / 100);
3249. if (strpos($cl, '%')>0) $cl = $x * (str_replace('%','',$cl) / 100);
3250. if (strpos($ct, 'px')>0) $ct = str_replace('px','',$ct);
3251. if (strpos($cr, 'px')>0) $cr = str_replace('px','',$cr);
3252. if (strpos($cb, 'px')>0) $cb = str_replace('px','',$cb);
3253. if (strpos($cl, 'px')>0) $cl = str_replace('px','',$cl);
3254. $ct = (int) $ct; $cr = (int) $cr; $cb = (int) $cb; $cl = (int) $cl;
3255. if ($round) {
3256. $ct = round($ct);
3257. $cr = round($cr);
3258. $cb = round($cb);
3259. $cl = round($cl);
3260. }
3261. if (!$negative) {
3262. if ($ct < 0) $ct = 0;
3263. if ($cr < 0) $cr = 0;
3264. if ($cb < 0) $cb = 0;
3265. if ($cl < 0) $cl = 0;
3266. }
3267. return array($ct, $cr, $cb, $cl);
3268. }
3270. /**
3271. * Creates a container image
3272. *
3273. * @access private
3274. * @param integer $x Width
3275. * @param integer $y Height
3276. * @param boolean $fill Optional flag to draw the background color or not
3277. * @param boolean $trsp Optional flag to set the background to be transparent
3278. * @return resource Container image
3279. */
3280. function imagecreatenew($x, $y, $fill = true, $trsp = false) {
3281. if ($x < 1) $x = 1; if ($y < 1) $y = 1;
3282. if ($this->gdversion() >= 2 && !$this->image_is_palette) {
3283. // create a true color image
3284. $dst_im = imagecreatetruecolor($x, $y);
3285. // this preserves transparency in PNGs, in true color
3286. if (empty($this->image_background_color) || $trsp) {
3287. imagealphablending($dst_im, false );
3288. imagefilledrectangle($dst_im, 0, 0, $x, $y, imagecolorallocatealpha($dst_im, 0, 0, 0, 127));
3289. }
3290. } else {
3291. // creates a palette image
3292. $dst_im = imagecreate($x, $y);
3293. // preserves transparency for palette images, if the original image has transparency
3294. if (($fill && $this->image_is_transparent && empty($this->image_background_color)) || $trsp) {
3295. imagefilledrectangle($dst_im, 0, 0, $x, $y, $this->image_transparent_color);
3296. imagecolortransparent($dst_im, $this->image_transparent_color);
3297. }
3298. }
3299. // fills with background color if any is set
3300. if ($fill && !empty($this->image_background_color) && !$trsp) {
3301. list($red, $green, $blue) = $this->getcolors($this->image_background_color);
3302. $background_color = imagecolorallocate($dst_im, $red, $green, $blue);
3303. imagefilledrectangle($dst_im, 0, 0, $x, $y, $background_color);
3304. }
3305. return $dst_im;
3306. }
3309. /**
3310. * Transfers an image from the container to the destination image
3311. *
3312. * @access private
3313. * @param resource $src_im Container image
3314. * @param resource $dst_im Destination image
3315. * @return resource Destination image
3316. */
3317. function imagetransfer($src_im, $dst_im) {
3318. if (is_resource($dst_im)) imagedestroy($dst_im);
3319. $dst_im = & $src_im;
3320. return $dst_im;
3321. }
3323. /**
3324. * Merges two images
3325. *
3326. * If the output format is PNG, then we do it pixel per pixel to retain the alpha channel
3327. *
3328. * @access private
3329. * @param resource $dst_img Destination image
3330. * @param resource $src_img Overlay image
3331. * @param int $dst_x x-coordinate of destination point
3332. * @param int $dst_y y-coordinate of destination point
3333. * @param int $src_x x-coordinate of source point
3334. * @param int $src_y y-coordinate of source point
3335. * @param int $src_w Source width
3336. * @param int $src_h Source height
3337. * @param int $pct Optional percentage of the overlay, between 0 and 100 (default: 100)
3338. * @return resource Destination image
3339. */
3340. function imagecopymergealpha(&$dst_im, &$src_im, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h, $pct = 0) {
3341. $dst_x = (int) $dst_x;
3342. $dst_y = (int) $dst_y;
3343. $src_x = (int) $src_x;
3344. $src_y = (int) $src_y;
3345. $src_w = (int) $src_w;
3346. $src_h = (int) $src_h;
3347. $pct = (int) $pct;
3348. $dst_w = imagesx($dst_im);
3349. $dst_h = imagesy($dst_im);
3351. for ($y = $src_y; $y < $src_h; $y++) {
3352. for ($x = $src_x; $x < $src_w; $x++) {
3354. if ($x + $dst_x >= 0 && $x + $dst_x < $dst_w && $x + $src_x >= 0 && $x + $src_x < $src_w
3355. && $y + $dst_y >= 0 && $y + $dst_y < $dst_h && $y + $src_y >= 0 && $y + $src_y < $src_h) {
3357. $dst_pixel = imagecolorsforindex($dst_im, imagecolorat($dst_im, $x + $dst_x, $y + $dst_y));
3358. $src_pixel = imagecolorsforindex($src_im, imagecolorat($src_im, $x + $src_x, $y + $src_y));
3360. $src_alpha = 1 - ($src_pixel['alpha'] / 127);
3361. $dst_alpha = 1 - ($dst_pixel['alpha'] / 127);
3362. $opacity = $src_alpha * $pct / 100;
3363. if ($dst_alpha >= $opacity) $alpha = $dst_alpha;
3364. if ($dst_alpha < $opacity) $alpha = $opacity;
3365. if ($alpha > 1) $alpha = 1;
3367. if ($opacity > 0) {
3368. $dst_red = round(( ($dst_pixel['red'] * $dst_alpha * (1 - $opacity)) ) );
3369. $dst_green = round(( ($dst_pixel['green'] * $dst_alpha * (1 - $opacity)) ) );
3370. $dst_blue = round(( ($dst_pixel['blue'] * $dst_alpha * (1 - $opacity)) ) );
3371. $src_red = round((($src_pixel['red'] * $opacity)) );
3372. $src_green = round((($src_pixel['green'] * $opacity)) );
3373. $src_blue = round((($src_pixel['blue'] * $opacity)) );
3374. $red = round(($dst_red + $src_red ) / ($dst_alpha * (1 - $opacity) + $opacity));
3375. $green = round(($dst_green + $src_green) / ($dst_alpha * (1 - $opacity) + $opacity));
3376. $blue = round(($dst_blue + $src_blue ) / ($dst_alpha * (1 - $opacity) + $opacity));
3377. if ($red > 255) $red = 255;
3378. if ($green > 255) $green = 255;
3379. if ($blue > 255) $blue = 255;
3380. $alpha = round((1 - $alpha) * 127);
3381. $color = imagecolorallocatealpha($dst_im, $red, $green, $blue, $alpha);
3382. imagesetpixel($dst_im, $x + $dst_x, $y + $dst_y, $color);
3383. }
3384. }
3385. }
3386. }
3387. return true;
3388. }
3392. /**
3393. * Actually uploads the file, and act on it according to the set processing class variables
3394. *
3395. * This function copies the uploaded file to the given location, eventually performing actions on it.
3396. * Typically, you can call {@link process} several times for the same file,
3397. * for instance to create a resized image and a thumbnail of the same file.
3398. * The original uploaded file remains intact in its temporary location, so you can use {@link process} several times.
3399. * You will be able to delete the uploaded file with {@link clean} when you have finished all your {@link process} calls.
3400. *
3401. * According to the processing class variables set in the calling file, the file can be renamed,
3402. * and if it is an image, can be resized or converted.
3403. *
3404. * When the processing is completed, and the file copied to its new location, the
3405. * processing class variables will be reset to their default value.
3406. * This allows you to set new properties, and perform another {@link process} on the same uploaded file
3407. *
3408. * If the function is called with a null or empty argument, then it will return the content of the picture
3409. *
3410. * It will set {@link processed} (and {@link error} is an error occurred)
3411. *
3412. * @access public
3413. * @param string $server_path Optional path location of the uploaded file, with an ending slash
3414. * @return string Optional content of the image
3415. */
3416. function process($server_path = null) {
3417. $this->error = '';
3418. $this->processed = true;
3419. $return_mode = false;
3420. $return_content = null;
3422. // clean up dst variables
3423. $this->file_dst_path = '';
3424. $this->file_dst_pathname = '';
3425. $this->file_dst_name = '';
3426. $this->file_dst_name_body = '';
3427. $this->file_dst_name_ext = '';
3429. // clean up some parameters
3430. $this->file_max_size = $this->getsize($this->file_max_size);
3431. $this->jpeg_size = $this->getsize($this->jpeg_size);
3432. // some parameters are being deprecated, and replaced with others
3433. if (is_null($this->image_overlay_opacity)) $this->image_overlay_opacity = $this->image_overlay_percent;
3434. if ($this->image_text_opacity == 100) $this->image_text_opacity = $this->image_text_percent;
3435. if ($this->image_text_background_opacity == 100) $this->image_text_background_opacity = $this->image_text_background_percent;
3437. // copy some variables as we need to keep them clean
3438. $file_src_name = $this->file_src_name;
3439. $file_src_name_body = $this->file_src_name_body;
3440. $file_src_name_ext = $this->file_src_name_ext;
3442. if (!$this->uploaded) {
3443. $this->error = $this->translate('file_not_uploaded');
3444. $this->processed = false;
3445. }
3447. if ($this->processed) {
3448. if (empty($server_path) || is_null($server_path)) {
3449. $this->log .= '<b>process file and return the content</b><br />';
3450. $return_mode = true;
3451. } else {
3452. if(strtolower(substr(PHP_OS, 0, 3)) === 'win') {
3453. if (substr($server_path, -1, 1) != '\\') $server_path = $server_path . '\\';
3454. } else {
3455. if (substr($server_path, -1, 1) != '/') $server_path = $server_path . '/';
3456. }
3457. $this->log .= '<b>process file to ' . $server_path . '</b><br />';
3458. }
3459. }
3461. if ($this->processed) {
3462. // checks file max size
3463. if ($this->file_src_size > $this->file_max_size) {
3464. $this->processed = false;
3465. $this->error = $this->translate('file_too_big');
3466. } else {
3467. $this->log .= '- file size OK<br />';
3468. }
3469. }
3471. if ($this->processed) {
3472. // if we have an image without extension, set it
3473. if ($this->file_force_extension && $this->file_is_image && !$this->file_src_name_ext) $file_src_name_ext = $this->image_src_type;
3474. // turn dangerous scripts into text files
3475. if ($this->no_script) {
3476. // if the file has no extension, we try to guess it from the MIME type
3477. if ($this->file_force_extension && empty($file_src_name_ext)) {
3478. if ($key = array_search($this->file_src_mime, $this->mime_types)) {
3479. $file_src_name_ext = $key;
3480. $file_src_name = $file_src_name_body . '.' . $file_src_name_ext;
3481. $this->log .= '- file renamed as ' . $file_src_name_body . '.' . $file_src_name_ext . '!<br />';
3482. }
3483. }
3484. // if the file is text based, or has a dangerous extension, we rename it as .txt
3485. if ((((substr($this->file_src_mime, 0, 5) == 'text/' && $this->file_src_mime != 'text/rtf') || strpos($this->file_src_mime, 'javascript') !== false) && (substr($file_src_name, -4) != '.txt'))
3486. || preg_match('/\.(php|php5|php4|php3|phtml|pl|py|cgi|asp|js)$/i', $this->file_src_name)
3487. || $this->file_force_extension && empty($file_src_name_ext)) {
3488. $this->file_src_mime = 'text/plain';
3489. if ($this->file_src_name_ext) $file_src_name_body = $file_src_name_body . '.' . $this->file_src_name_ext;
3490. $file_src_name_ext = 'txt';
3491. $file_src_name = $file_src_name_body . '.' . $file_src_name_ext;
3492. $this->log .= '- script renamed as ' . $file_src_name_body . '.' . $file_src_name_ext . '!<br />';
3493. }
3494. }
3496. if ($this->mime_check && empty($this->file_src_mime)) {
3497. $this->processed = false;
3498. $this->error = $this->translate('no_mime');
3499. } else if ($this->mime_check && !empty($this->file_src_mime) && strpos($this->file_src_mime, '/') !== false) {
3500. list($m1, $m2) = explode('/', $this->file_src_mime);
3501. $allowed = false;
3502. // check wether the mime type is allowed
3503. if (!is_array($this->allowed)) $this->allowed = array($this->allowed);
3504. foreach($this->allowed as $k => $v) {
3505. list($v1, $v2) = explode('/', $v);
3506. if (($v1 == '*' && $v2 == '*') || ($v1 == $m1 && ($v2 == $m2 || $v2 == '*'))) {
3507. $allowed = true;
3508. break;
3509. }
3510. }
3511. // check wether the mime type is forbidden
3512. if (!is_array($this->forbidden)) $this->forbidden = array($this->forbidden);
3513. foreach($this->forbidden as $k => $v) {
3514. list($v1, $v2) = explode('/', $v);
3515. if (($v1 == '*' && $v2 == '*') || ($v1 == $m1 && ($v2 == $m2 || $v2 == '*'))) {
3516. $allowed = false;
3517. break;
3518. }
3519. }
3520. if (!$allowed) {
3521. $this->processed = false;
3522. $this->error = $this->translate('incorrect_file');
3523. } else {
3524. $this->log .= '- file mime OK : ' . $this->file_src_mime . '<br />';
3525. }
3526. } else {
3527. $this->log .= '- file mime (not checked) : ' . $this->file_src_mime . '<br />';
3528. }
3530. // if the file is an image, we can check on its dimensions
3531. // these checks are not available if open_basedir restrictions are in place
3532. if ($this->file_is_image) {
3533. if (is_numeric($this->image_src_x) && is_numeric($this->image_src_y)) {
3534. $ratio = $this->image_src_x / $this->image_src_y;
3535. if (!is_null($this->image_max_width) && $this->image_src_x > $this->image_max_width) {
3536. $this->processed = false;
3537. $this->error = $this->translate('image_too_wide');
3538. }
3539. if (!is_null($this->image_min_width) && $this->image_src_x < $this->image_min_width) {
3540. $this->processed = false;
3541. $this->error = $this->translate('image_too_narrow');
3542. }
3543. if (!is_null($this->image_max_height) && $this->image_src_y > $this->image_max_height) {
3544. $this->processed = false;
3545. $this->error = $this->translate('image_too_high');
3546. }
3547. if (!is_null($this->image_min_height) && $this->image_src_y < $this->image_min_height) {
3548. $this->processed = false;
3549. $this->error = $this->translate('image_too_short');
3550. }
3551. if (!is_null($this->image_max_ratio) && $ratio > $this->image_max_ratio) {
3552. $this->processed = false;
3553. $this->error = $this->translate('ratio_too_high');
3554. }
3555. if (!is_null($this->image_min_ratio) && $ratio < $this->image_min_ratio) {
3556. $this->processed = false;
3557. $this->error = $this->translate('ratio_too_low');
3558. }
3559. if (!is_null($this->image_max_pixels) && $this->image_src_pixels > $this->image_max_pixels) {
3560. $this->processed = false;
3561. $this->error = $this->translate('too_many_pixels');
3562. }
3563. if (!is_null($this->image_min_pixels) && $this->image_src_pixels < $this->image_min_pixels) {
3564. $this->processed = false;
3565. $this->error = $this->translate('not_enough_pixels');
3566. }
3567. } else {
3568. $this->log .= '- no image properties available, can\'t enforce dimension checks : ' . $this->file_src_mime . '<br />';
3569. }
3570. }
3571. }
3573. if ($this->processed) {
3574. $this->file_dst_path = $server_path;
3576. // repopulate dst variables from src
3577. $this->file_dst_name = $file_src_name;
3578. $this->file_dst_name_body = $file_src_name_body;
3579. $this->file_dst_name_ext = $file_src_name_ext;
3580. if ($this->file_overwrite) $this->file_auto_rename = false;
3582. if ($this->image_convert && $this->file_is_image) { // if we convert as an image
3583. if ($this->file_src_name_ext) $this->file_dst_name_ext = $this->image_convert;
3584. $this->log .= '- new file name ext : ' . $this->image_convert . '<br />';
3585. }
3586. if (!is_null($this->file_new_name_body)) { // rename file body
3587. $this->file_dst_name_body = $this->file_new_name_body;
3588. $this->log .= '- new file name body : ' . $this->file_new_name_body . '<br />';
3589. }
3590. if (!is_null($this->file_new_name_ext)) { // rename file ext
3591. $this->file_dst_name_ext = $this->file_new_name_ext;
3592. $this->log .= '- new file name ext : ' . $this->file_new_name_ext . '<br />';
3593. }
3594. if (!is_null($this->file_name_body_add)) { // append a string to the name
3595. $this->file_dst_name_body = $this->file_dst_name_body . $this->file_name_body_add;
3596. $this->log .= '- file name body append : ' . $this->file_name_body_add . '<br />';
3597. }
3598. if (!is_null($this->file_name_body_pre)) { // prepend a string to the name
3599. $this->file_dst_name_body = $this->file_name_body_pre . $this->file_dst_name_body;
3600. $this->log .= '- file name body prepend : ' . $this->file_name_body_pre . '<br />';
3601. }
3602. if ($this->file_safe_name) { // formats the name
3603. $this->file_dst_name_body = utf8_encode(strtr(utf8_decode($this->file_dst_name_body), utf8_decode('ŠŽšžŸÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÑÒÓÔÕÖØÙÚÛÜÝàáâãäåçèéêëìíîïñòóôõöøùúûüýÿ'), 'SZszYAAAAAACEEEEIIIINOOOOOOUUUUYaaaaaaceeeeiiiinoooooouuuuyy'));
3604. $this->file_dst_name_body = strtr($this->file_dst_name_body, array('Þ' => 'TH', 'þ' => 'th', 'Ð' => 'DH', 'ð' => 'dh', 'ß' => 'ss', 'Œ' => 'OE', 'œ' => 'oe', 'Æ' => 'AE', 'æ' => 'ae', 'µ' => 'u'));
3605. $this->file_dst_name_body = preg_replace(array('/\s/', '/\.[\.]+/', '/[^\w_\.\-]/'), array('_', '.', ''), $this->file_dst_name_body);
3606. $this->log .= '- file name safe format<br />';
3607. }
3609. $this->log .= '- destination variables<br />';
3610. if (empty($this->file_dst_path) || is_null($this->file_dst_path)) {
3611. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;file_dst_path : n/a<br />';
3612. } else {
3613. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;file_dst_path : ' . $this->file_dst_path . '<br />';
3614. }
3615. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;file_dst_name_body : ' . $this->file_dst_name_body . '<br />';
3616. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;file_dst_name_ext : ' . $this->file_dst_name_ext . '<br />';
3618. // do we do some image manipulation?
3619. $image_manipulation = ($this->file_is_image && (
3620. $this->image_resize
3621. || $this->image_convert != ''
3622. || is_numeric($this->image_brightness)
3623. || is_numeric($this->image_contrast)
3624. || is_numeric($this->image_opacity)
3625. || is_numeric($this->image_threshold)
3626. || !empty($this->image_tint_color)
3627. || !empty($this->image_overlay_color)
3628. || $this->image_pixelate
3629. || $this->image_unsharp
3630. || !empty($this->image_text)
3631. || $this->image_greyscale
3632. || $this->image_negative
3633. || !empty($this->image_watermark)
3634. || is_numeric($this->image_rotate)
3635. || is_numeric($this->jpeg_size)
3636. || !empty($this->image_flip)
3637. || !empty($this->image_crop)
3638. || !empty($this->image_precrop)
3639. || !empty($this->image_border)
3640. || !empty($this->image_border_transparent)
3641. || $this->image_frame > 0
3642. || $this->image_bevel > 0
3643. || $this->image_reflection_height));
3645. // set the destination file name
3646. $this->file_dst_name = $this->file_dst_name_body . (!empty($this->file_dst_name_ext) ? '.' . $this->file_dst_name_ext : '');
3648. if (!$return_mode) {
3649. if (!$this->file_auto_rename) {
3650. $this->log .= '- no auto_rename if same filename exists<br />';
3651. $this->file_dst_pathname = $this->file_dst_path . $this->file_dst_name;
3652. } else {
3653. $this->log .= '- checking for auto_rename<br />';
3654. $this->file_dst_pathname = $this->file_dst_path . $this->file_dst_name;
3655. $body = $this->file_dst_name_body;
3656. $ext = '';
3657. // if we have changed the extension, then we add our increment before
3658. if ($file_src_name_ext != $this->file_src_name_ext) {
3659. if (substr($this->file_dst_name_body, -1 - strlen($this->file_src_name_ext)) == '.' . $this->file_src_name_ext) {
3660. $body = substr($this->file_dst_name_body, 0, strlen($this->file_dst_name_body) - 1 - strlen($this->file_src_name_ext));
3661. $ext = '.' . $this->file_src_name_ext;
3662. }
3663. }
3664. $cpt = 1;
3665. while (@file_exists($this->file_dst_pathname)) {
3666. $this->file_dst_name_body = $body . '_' . $cpt . $ext;
3667. $this->file_dst_name = $this->file_dst_name_body . (!empty($this->file_dst_name_ext) ? '.' . $this->file_dst_name_ext : '');
3668. $cpt++;
3669. $this->file_dst_pathname = $this->file_dst_path . $this->file_dst_name;
3670. }
3671. if ($cpt>1) $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;auto_rename to ' . $this->file_dst_name . '<br />';
3672. }
3674. $this->log .= '- destination file details<br />';
3675. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;file_dst_name : ' . $this->file_dst_name . '<br />';
3676. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;file_dst_pathname : ' . $this->file_dst_pathname . '<br />';
3678. if ($this->file_overwrite) {
3679. $this->log .= '- no overwrite checking<br />';
3680. } else {
3681. if (@file_exists($this->file_dst_pathname)) {
3682. $this->processed = false;
3683. $this->error = $this->translate('already_exists', array($this->file_dst_name));
3684. } else {
3685. $this->log .= '- ' . $this->file_dst_name . ' doesn\'t exist already<br />';
3686. }
3687. }
3688. }
3689. }
3691. if ($this->processed) {
3692. // if we have already moved the uploaded file, we use the temporary copy as source file, and check if it exists
3693. if (!empty($this->file_src_temp)) {
3694. $this->log .= '- use the temp file instead of the original file since it is a second process<br />';
3695. $this->file_src_pathname = $this->file_src_temp;
3696. if (!file_exists($this->file_src_pathname)) {
3697. $this->processed = false;
3698. $this->error = $this->translate('temp_file_missing');
3699. }
3700. // if we haven't a temp file, and that we do check on uploads, we use is_uploaded_file()
3701. } else if (!$this->no_upload_check) {
3702. if (!is_uploaded_file($this->file_src_pathname)) {
3703. $this->processed = false;
3704. $this->error = $this->translate('source_missing');
3705. }
3706. // otherwise, if we don't check on uploaded files (local file for instance), we use file_exists()
3707. } else {
3708. if (!file_exists($this->file_src_pathname)) {
3709. $this->processed = false;
3710. $this->error = $this->translate('source_missing');
3711. }
3712. }
3714. // checks if the destination directory exists, and attempt to create it
3715. if (!$return_mode) {
3716. if ($this->processed && !file_exists($this->file_dst_path)) {
3717. if ($this->dir_auto_create) {
3718. $this->log .= '- ' . $this->file_dst_path . ' doesn\'t exist. Attempting creation:';
3719. if (!$this->rmkdir($this->file_dst_path, $this->dir_chmod)) {
3720. $this->log .= ' failed<br />';
3721. $this->processed = false;
3722. $this->error = $this->translate('destination_dir');
3723. } else {
3724. $this->log .= ' success<br />';
3725. }
3726. } else {
3727. $this->error = $this->translate('destination_dir_missing');
3728. }
3729. }
3731. if ($this->processed && !is_dir($this->file_dst_path)) {
3732. $this->processed = false;
3733. $this->error = $this->translate('destination_path_not_dir');
3734. }
3736. // checks if the destination directory is writeable, and attempt to make it writeable
3737. $hash = md5($this->file_dst_name_body . rand(1, 1000));
3738. if ($this->processed && !($f = @fopen($this->file_dst_path . $hash . (!empty($this->file_dst_name_ext) ? '.' . $this->file_dst_name_ext : ''), 'a+'))) {
3739. if ($this->dir_auto_chmod) {
3740. $this->log .= '- ' . $this->file_dst_path . ' is not writeable. Attempting chmod:';
3741. if (!@chmod($this->file_dst_path, $this->dir_chmod)) {
3742. $this->log .= ' failed<br />';
3743. $this->processed = false;
3744. $this->error = $this->translate('destination_dir_write');
3745. } else {
3746. $this->log .= ' success<br />';
3747. if (!($f = @fopen($this->file_dst_path . $hash . (!empty($this->file_dst_name_ext) ? '.' . $this->file_dst_name_ext : ''), 'a+'))) { // we re-check
3748. $this->processed = false;
3749. $this->error = $this->translate('destination_dir_write');
3750. } else {
3751. @fclose($f);
3752. }
3753. }
3754. } else {
3755. $this->processed = false;
3756. $this->error = $this->translate('destination_path_write');
3757. }
3758. } else {
3759. if ($this->processed) @fclose($f);
3760. @unlink($this->file_dst_path . $hash . (!empty($this->file_dst_name_ext) ? '.' . $this->file_dst_name_ext : ''));
3761. }
3764. // if we have an uploaded file, and if it is the first process, and if we can't access the file directly (open_basedir restriction)
3765. // then we create a temp file that will be used as the source file in subsequent processes
3766. // the third condition is there to check if the file is not accessible *directly* (it already has positively gone through is_uploaded_file(), so it exists)
3767. if (!$this->no_upload_check && empty($this->file_src_temp) && !@file_exists($this->file_src_pathname)) {
3768. $this->log .= '- attempting to use a temp file:';
3769. $hash = md5($this->file_dst_name_body . rand(1, 1000));
3770. if (move_uploaded_file($this->file_src_pathname, $this->file_dst_path . $hash . (!empty($this->file_dst_name_ext) ? '.' . $this->file_dst_name_ext : ''))) {
3771. $this->file_src_pathname = $this->file_dst_path . $hash . (!empty($this->file_dst_name_ext) ? '.' . $this->file_dst_name_ext : '');
3772. $this->file_src_temp = $this->file_src_pathname;
3773. $this->log .= ' file created<br />';
3774. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;temp file is: ' . $this->file_src_temp . '<br />';
3775. } else {
3776. $this->log .= ' failed<br />';
3777. $this->processed = false;
3778. $this->error = $this->translate('temp_file');
3779. }
3780. }
3781. }
3782. }
3784. if ($this->processed) {
3786. // we do a quick check to ensure the file is really an image
3787. // we can do this only now, as it would have failed before in case of open_basedir
3788. if ($image_manipulation && !@getimagesize($this->file_src_pathname)) {
3789. $this->log .= '- the file is not an image!<br />';
3790. $image_manipulation = false;
3791. }
3793. if ($image_manipulation) {
3795. // make sure GD doesn't complain too much
3796. ini_set("gd.jpeg_ignore_warning", 1);
3798. // checks if the source file is readable
3799. if ($this->processed && !($f = @fopen($this->file_src_pathname, 'r'))) {
3800. $this->processed = false;
3801. $this->error = $this->translate('source_not_readable');
3802. } else {
3803. @fclose($f);
3804. }
3806. // we now do all the image manipulations
3807. $this->log .= '- image resizing or conversion wanted<br />';
3808. if ($this->gdversion()) {
3809. switch($this->image_src_type) {
3810. case 'jpg':
3811. if (!function_exists('imagecreatefromjpeg')) {
3812. $this->processed = false;
3813. $this->error = $this->translate('no_create_support', array('JPEG'));
3814. } else {
3815. $image_src = @imagecreatefromjpeg($this->file_src_pathname);
3816. if (!$image_src) {
3817. $this->processed = false;
3818. $this->error = $this->translate('create_error', array('JPEG'));
3819. } else {
3820. $this->log .= '- source image is JPEG<br />';
3821. }
3822. }
3823. break;
3824. case 'png':
3825. if (!function_exists('imagecreatefrompng')) {
3826. $this->processed = false;
3827. $this->error = $this->translate('no_create_support', array('PNG'));
3828. } else {
3829. $image_src = @imagecreatefrompng($this->file_src_pathname);
3830. if (!$image_src) {
3831. $this->processed = false;
3832. $this->error = $this->translate('create_error', array('PNG'));
3833. } else {
3834. $this->log .= '- source image is PNG<br />';
3835. }
3836. }
3837. break;
3838. case 'gif':
3839. if (!function_exists('imagecreatefromgif')) {
3840. $this->processed = false;
3841. $this->error = $this->translate('no_create_support', array('GIF'));
3842. } else {
3843. $image_src = @imagecreatefromgif($this->file_src_pathname);
3844. if (!$image_src) {
3845. $this->processed = false;
3846. $this->error = $this->translate('create_error', array('GIF'));
3847. } else {
3848. $this->log .= '- source image is GIF<br />';
3849. }
3850. }
3851. break;
3852. case 'bmp':
3853. if (!method_exists($this, 'imagecreatefrombmp')) {
3854. $this->processed = false;
3855. $this->error = $this->translate('no_create_support', array('BMP'));
3856. } else {
3857. $image_src = @$this->imagecreatefrombmp($this->file_src_pathname);
3858. if (!$image_src) {
3859. $this->processed = false;
3860. $this->error = $this->translate('create_error', array('BMP'));
3861. } else {
3862. $this->log .= '- source image is BMP<br />';
3863. }
3864. }
3865. break;
3866. default:
3867. $this->processed = false;
3868. $this->error = $this->translate('source_invalid');
3869. }
3870. } else {
3871. $this->processed = false;
3872. $this->error = $this->translate('gd_missing');
3873. }
3875. if ($this->processed && $image_src) {
3877. // we have to set image_convert if it is not already
3878. if (empty($this->image_convert)) {
3879. $this->log .= '- setting destination file type to ' . $this->image_src_type . '<br />';
3880. $this->image_convert = $this->image_src_type;
3881. }
3883. if (!in_array($this->image_convert, $this->image_supported)) {
3884. $this->image_convert = 'jpg';
3885. }
3887. // we set the default color to be the background color if we don't output in a transparent format
3888. if ($this->image_convert != 'png' && $this->image_convert != 'gif' && !empty($this->image_default_color) && empty($this->image_background_color)) $this->image_background_color = $this->image_default_color;
3889. if (!empty($this->image_background_color)) $this->image_default_color = $this->image_background_color;
3890. if (empty($this->image_default_color)) $this->image_default_color = '#FFFFFF';
3892. $this->image_src_x = imagesx($image_src);
3893. $this->image_src_y = imagesy($image_src);
3894. $gd_version = $this->gdversion();
3895. $ratio_crop = null;
3897. if (!imageistruecolor($image_src)) { // $this->image_src_type == 'gif'
3898. $this->log .= '- image is detected as having a palette<br />';
3899. $this->image_is_palette = true;
3900. $this->image_transparent_color = imagecolortransparent($image_src);
3901. if ($this->image_transparent_color >= 0 && imagecolorstotal($image_src) > $this->image_transparent_color) {
3902. $this->image_is_transparent = true;
3903. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;palette image is detected as transparent<br />';
3904. }
3905. // if the image has a palette (GIF), we convert it to true color, preserving transparency
3906. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;convert palette image to true color<br />';
3907. $true_color = imagecreatetruecolor($this->image_src_x, $this->image_src_y);
3908. imagealphablending($true_color, false);
3909. imagesavealpha($true_color, true);
3910. for ($x = 0; $x < $this->image_src_x; $x++) {
3911. for ($y = 0; $y < $this->image_src_y; $y++) {
3912. if ($this->image_transparent_color >= 0 && imagecolorat($image_src, $x, $y) == $this->image_transparent_color) {
3913. imagesetpixel($true_color, $x, $y, 127 << 24);
3914. } else {
3915. $rgb = imagecolorsforindex($image_src, imagecolorat($image_src, $x, $y));
3916. imagesetpixel($true_color, $x, $y, ($rgb['alpha'] << 24) | ($rgb['red'] << 16) | ($rgb['green'] << 8) | $rgb['blue']);
3917. }
3918. }
3919. }
3920. $image_src = $this->imagetransfer($true_color, $image_src);
3921. imagealphablending($image_src, false);
3922. imagesavealpha($image_src, true);
3923. $this->image_is_palette = false;
3924. }
3927. $image_dst = & $image_src;
3929. // pre-crop image, before resizing
3930. if ((!empty($this->image_precrop))) {
3931. list($ct, $cr, $cb, $cl) = $this->getoffsets($this->image_precrop, $this->image_src_x, $this->image_src_y, true, true);
3932. $this->log .= '- pre-crop image : ' . $ct . ' ' . $cr . ' ' . $cb . ' ' . $cl . ' <br />';
3933. $this->image_src_x = $this->image_src_x - $cl - $cr;
3934. $this->image_src_y = $this->image_src_y - $ct - $cb;
3935. if ($this->image_src_x < 1) $this->image_src_x = 1;
3936. if ($this->image_src_y < 1) $this->image_src_y = 1;
3937. $tmp = $this->imagecreatenew($this->image_src_x, $this->image_src_y);
3939. // we copy the image into the recieving image
3940. imagecopy($tmp, $image_dst, 0, 0, $cl, $ct, $this->image_src_x, $this->image_src_y);
3942. // if we crop with negative margins, we have to make sure the extra bits are the right color, or transparent
3943. if ($ct < 0 || $cr < 0 || $cb < 0 || $cl < 0 ) {
3944. // use the background color if present
3945. if (!empty($this->image_background_color)) {
3946. list($red, $green, $blue) = $this->getcolors($this->image_background_color);
3947. $fill = imagecolorallocate($tmp, $red, $green, $blue);
3948. } else {
3949. $fill = imagecolorallocatealpha($tmp, 0, 0, 0, 127);
3950. }
3951. // fills eventual negative margins
3952. if ($ct < 0) imagefilledrectangle($tmp, 0, 0, $this->image_src_x, -$ct, $fill);
3953. if ($cr < 0) imagefilledrectangle($tmp, $this->image_src_x + $cr, 0, $this->image_src_x, $this->image_src_y, $fill);
3954. if ($cb < 0) imagefilledrectangle($tmp, 0, $this->image_src_y + $cb, $this->image_src_x, $this->image_src_y, $fill);
3955. if ($cl < 0) imagefilledrectangle($tmp, 0, 0, -$cl, $this->image_src_y, $fill);
3956. }
3958. // we transfert tmp into image_dst
3959. $image_dst = $this->imagetransfer($tmp, $image_dst);
3960. }
3962. // resize image (and move image_src_x, image_src_y dimensions into image_dst_x, image_dst_y)
3963. if ($this->image_resize) {
3964. $this->log .= '- resizing...<br />';
3966. if ($this->image_ratio_x) {
3967. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;calculate x size<br />';
3968. $this->image_dst_x = round(($this->image_src_x * $this->image_y) / $this->image_src_y);
3969. $this->image_dst_y = $this->image_y;
3970. } else if ($this->image_ratio_y) {
3971. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;calculate y size<br />';
3972. $this->image_dst_x = $this->image_x;
3973. $this->image_dst_y = round(($this->image_src_y * $this->image_x) / $this->image_src_x);
3974. } else if (is_numeric($this->image_ratio_pixels)) {
3975. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;calculate x/y size to match a number of pixels<br />';
3976. $pixels = $this->image_src_y * $this->image_src_x;
3977. $diff = sqrt($this->image_ratio_pixels / $pixels);
3978. $this->image_dst_x = round($this->image_src_x * $diff);
3979. $this->image_dst_y = round($this->image_src_y * $diff);
3980. } else if ($this->image_ratio || $this->image_ratio_crop || $this->image_ratio_fill || $this->image_ratio_no_zoom_in || $this->image_ratio_no_zoom_out) {
3981. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;check x/y sizes<br />';
3982. if ((!$this->image_ratio_no_zoom_in && !$this->image_ratio_no_zoom_out)
3983. || ($this->image_ratio_no_zoom_in && ($this->image_src_x > $this->image_x || $this->image_src_y > $this->image_y))
3984. || ($this->image_ratio_no_zoom_out && $this->image_src_x < $this->image_x && $this->image_src_y < $this->image_y)) {
3985. $this->image_dst_x = $this->image_x;
3986. $this->image_dst_y = $this->image_y;
3987. if ($this->image_ratio_crop) {
3988. if (!is_string($this->image_ratio_crop)) $this->image_ratio_crop = '';
3989. $this->image_ratio_crop = strtolower($this->image_ratio_crop);
3990. if (($this->image_src_x/$this->image_x) > ($this->image_src_y/$this->image_y)) {
3991. $this->image_dst_y = $this->image_y;
3992. $this->image_dst_x = intval($this->image_src_x*($this->image_y / $this->image_src_y));
3993. $ratio_crop = array();
3994. $ratio_crop['x'] = $this->image_dst_x - $this->image_x;
3995. if (strpos($this->image_ratio_crop, 'l') !== false) {
3996. $ratio_crop['l'] = 0;
3997. $ratio_crop['r'] = $ratio_crop['x'];
3998. } else if (strpos($this->image_ratio_crop, 'r') !== false) {
3999. $ratio_crop['l'] = $ratio_crop['x'];
4000. $ratio_crop['r'] = 0;
4001. } else {
4002. $ratio_crop['l'] = round($ratio_crop['x']/2);
4003. $ratio_crop['r'] = $ratio_crop['x'] - $ratio_crop['l'];
4004. }
4005. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;ratio_crop_x : ' . $ratio_crop['x'] . ' (' . $ratio_crop['l'] . ';' . $ratio_crop['r'] . ')<br />';
4006. if (is_null($this->image_crop)) $this->image_crop = array(0, 0, 0, 0);
4007. } else {
4008. $this->image_dst_x = $this->image_x;
4009. $this->image_dst_y = intval($this->image_src_y*($this->image_x / $this->image_src_x));
4010. $ratio_crop = array();
4011. $ratio_crop['y'] = $this->image_dst_y - $this->image_y;
4012. if (strpos($this->image_ratio_crop, 't') !== false) {
4013. $ratio_crop['t'] = 0;
4014. $ratio_crop['b'] = $ratio_crop['y'];
4015. } else if (strpos($this->image_ratio_crop, 'b') !== false) {
4016. $ratio_crop['t'] = $ratio_crop['y'];
4017. $ratio_crop['b'] = 0;
4018. } else {
4019. $ratio_crop['t'] = round($ratio_crop['y']/2);
4020. $ratio_crop['b'] = $ratio_crop['y'] - $ratio_crop['t'];
4021. }
4022. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;ratio_crop_y : ' . $ratio_crop['y'] . ' (' . $ratio_crop['t'] . ';' . $ratio_crop['b'] . ')<br />';
4023. if (is_null($this->image_crop)) $this->image_crop = array(0, 0, 0, 0);
4024. }
4025. } else if ($this->image_ratio_fill) {
4026. if (!is_string($this->image_ratio_fill)) $this->image_ratio_fill = '';
4027. $this->image_ratio_fill = strtolower($this->image_ratio_fill);
4028. if (($this->image_src_x/$this->image_x) < ($this->image_src_y/$this->image_y)) {
4029. $this->image_dst_y = $this->image_y;
4030. $this->image_dst_x = intval($this->image_src_x*($this->image_y / $this->image_src_y));
4031. $ratio_crop = array();
4032. $ratio_crop['x'] = $this->image_dst_x - $this->image_x;
4033. if (strpos($this->image_ratio_fill, 'l') !== false) {
4034. $ratio_crop['l'] = 0;
4035. $ratio_crop['r'] = $ratio_crop['x'];
4036. } else if (strpos($this->image_ratio_fill, 'r') !== false) {
4037. $ratio_crop['l'] = $ratio_crop['x'];
4038. $ratio_crop['r'] = 0;
4039. } else {
4040. $ratio_crop['l'] = round($ratio_crop['x']/2);
4041. $ratio_crop['r'] = $ratio_crop['x'] - $ratio_crop['l'];
4042. }
4043. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;ratio_fill_x : ' . $ratio_crop['x'] . ' (' . $ratio_crop['l'] . ';' . $ratio_crop['r'] . ')<br />';
4044. if (is_null($this->image_crop)) $this->image_crop = array(0, 0, 0, 0);
4045. } else {
4046. $this->image_dst_x = $this->image_x;
4047. $this->image_dst_y = intval($this->image_src_y*($this->image_x / $this->image_src_x));
4048. $ratio_crop = array();
4049. $ratio_crop['y'] = $this->image_dst_y - $this->image_y;
4050. if (strpos($this->image_ratio_fill, 't') !== false) {
4051. $ratio_crop['t'] = 0;
4052. $ratio_crop['b'] = $ratio_crop['y'];
4053. } else if (strpos($this->image_ratio_fill, 'b') !== false) {
4054. $ratio_crop['t'] = $ratio_crop['y'];
4055. $ratio_crop['b'] = 0;
4056. } else {
4057. $ratio_crop['t'] = round($ratio_crop['y']/2);
4058. $ratio_crop['b'] = $ratio_crop['y'] - $ratio_crop['t'];
4059. }
4060. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;ratio_fill_y : ' . $ratio_crop['y'] . ' (' . $ratio_crop['t'] . ';' . $ratio_crop['b'] . ')<br />';
4061. if (is_null($this->image_crop)) $this->image_crop = array(0, 0, 0, 0);
4062. }
4063. } else {
4064. if (($this->image_src_x/$this->image_x) > ($this->image_src_y/$this->image_y)) {
4065. $this->image_dst_x = $this->image_x;
4066. $this->image_dst_y = intval($this->image_src_y*($this->image_x / $this->image_src_x));
4067. } else {
4068. $this->image_dst_y = $this->image_y;
4069. $this->image_dst_x = intval($this->image_src_x*($this->image_y / $this->image_src_y));
4070. }
4071. }
4072. } else {
4073. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;doesn\'t calculate x/y sizes<br />';
4074. $this->image_dst_x = $this->image_src_x;
4075. $this->image_dst_y = $this->image_src_y;
4076. }
4077. } else {
4078. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;use plain sizes<br />';
4079. $this->image_dst_x = $this->image_x;
4080. $this->image_dst_y = $this->image_y;
4081. }
4083. if ($this->image_dst_x < 1) $this->image_dst_x = 1;
4084. if ($this->image_dst_y < 1) $this->image_dst_y = 1;
4085. $tmp = $this->imagecreatenew($this->image_dst_x, $this->image_dst_y);
4087. if ($gd_version >= 2) {
4088. $res = imagecopyresampled($tmp, $image_src, 0, 0, 0, 0, $this->image_dst_x, $this->image_dst_y, $this->image_src_x, $this->image_src_y);
4089. } else {
4090. $res = imagecopyresized($tmp, $image_src, 0, 0, 0, 0, $this->image_dst_x, $this->image_dst_y, $this->image_src_x, $this->image_src_y);
4091. }
4093. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;resized image object created<br />';
4094. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;image_src_x y : ' . $this->image_src_x . ' x ' . $this->image_src_y . '<br />';
4095. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;image_dst_x y : ' . $this->image_dst_x . ' x ' . $this->image_dst_y . '<br />';
4096. // we transfert tmp into image_dst
4097. $image_dst = $this->imagetransfer($tmp, $image_dst);
4099. } else {
4100. $this->image_dst_x = $this->image_src_x;
4101. $this->image_dst_y = $this->image_src_y;
4102. }
4104. // crop image (and also crops if image_ratio_crop is used)
4105. if ((!empty($this->image_crop) || !is_null($ratio_crop))) {
4106. list($ct, $cr, $cb, $cl) = $this->getoffsets($this->image_crop, $this->image_dst_x, $this->image_dst_y, true, true);
4107. // we adjust the cropping if we use image_ratio_crop
4108. if (!is_null($ratio_crop)) {
4109. if (array_key_exists('t', $ratio_crop)) $ct += $ratio_crop['t'];
4110. if (array_key_exists('r', $ratio_crop)) $cr += $ratio_crop['r'];
4111. if (array_key_exists('b', $ratio_crop)) $cb += $ratio_crop['b'];
4112. if (array_key_exists('l', $ratio_crop)) $cl += $ratio_crop['l'];
4113. }
4114. $this->log .= '- crop image : ' . $ct . ' ' . $cr . ' ' . $cb . ' ' . $cl . ' <br />';
4115. $this->image_dst_x = $this->image_dst_x - $cl - $cr;
4116. $this->image_dst_y = $this->image_dst_y - $ct - $cb;
4117. if ($this->image_dst_x < 1) $this->image_dst_x = 1;
4118. if ($this->image_dst_y < 1) $this->image_dst_y = 1;
4119. $tmp = $this->imagecreatenew($this->image_dst_x, $this->image_dst_y);
4121. // we copy the image into the recieving image
4122. imagecopy($tmp, $image_dst, 0, 0, $cl, $ct, $this->image_dst_x, $this->image_dst_y);
4124. // if we crop with negative margins, we have to make sure the extra bits are the right color, or transparent
4125. if ($ct < 0 || $cr < 0 || $cb < 0 || $cl < 0 ) {
4126. // use the background color if present
4127. if (!empty($this->image_background_color)) {
4128. list($red, $green, $blue) = $this->getcolors($this->image_background_color);
4129. $fill = imagecolorallocate($tmp, $red, $green, $blue);
4130. } else {
4131. $fill = imagecolorallocatealpha($tmp, 0, 0, 0, 127);
4132. }
4133. // fills eventual negative margins
4134. if ($ct < 0) imagefilledrectangle($tmp, 0, 0, $this->image_dst_x, -$ct-1, $fill);
4135. if ($cr < 0) imagefilledrectangle($tmp, $this->image_dst_x + $cr, 0, $this->image_dst_x, $this->image_dst_y, $fill);
4136. if ($cb < 0) imagefilledrectangle($tmp, 0, $this->image_dst_y + $cb, $this->image_dst_x, $this->image_dst_y, $fill);
4137. if ($cl < 0) imagefilledrectangle($tmp, 0, 0, -$cl-1, $this->image_dst_y, $fill);
4138. }
4140. // we transfert tmp into image_dst
4141. $image_dst = $this->imagetransfer($tmp, $image_dst);
4142. }
4144. // flip image
4145. if ($gd_version >= 2 && !empty($this->image_flip)) {
4146. $this->image_flip = strtolower($this->image_flip);
4147. $this->log .= '- flip image : ' . $this->image_flip . '<br />';
4148. $tmp = $this->imagecreatenew($this->image_dst_x, $this->image_dst_y);
4149. for ($x = 0; $x < $this->image_dst_x; $x++) {
4150. for ($y = 0; $y < $this->image_dst_y; $y++){
4151. if (strpos($this->image_flip, 'v') !== false) {
4152. imagecopy($tmp, $image_dst, $this->image_dst_x - $x - 1, $y, $x, $y, 1, 1);
4153. } else {
4154. imagecopy($tmp, $image_dst, $x, $this->image_dst_y - $y - 1, $x, $y, 1, 1);
4155. }
4156. }
4157. }
4158. // we transfert tmp into image_dst
4159. $image_dst = $this->imagetransfer($tmp, $image_dst);
4160. }
4162. // rotate image
4163. if ($gd_version >= 2 && is_numeric($this->image_rotate)) {
4164. if (!in_array($this->image_rotate, array(0, 90, 180, 270))) $this->image_rotate = 0;
4165. if ($this->image_rotate != 0) {
4166. if ($this->image_rotate == 90 || $this->image_rotate == 270) {
4167. $tmp = $this->imagecreatenew($this->image_dst_y, $this->image_dst_x);
4168. } else {
4169. $tmp = $this->imagecreatenew($this->image_dst_x, $this->image_dst_y);
4170. }
4171. $this->log .= '- rotate image : ' . $this->image_rotate . '<br />';
4172. for ($x = 0; $x < $this->image_dst_x; $x++) {
4173. for ($y = 0; $y < $this->image_dst_y; $y++){
4174. if ($this->image_rotate == 90) {
4175. imagecopy($tmp, $image_dst, $y, $x, $x, $this->image_dst_y - $y - 1, 1, 1);
4176. } else if ($this->image_rotate == 180) {
4177. imagecopy($tmp, $image_dst, $x, $y, $this->image_dst_x - $x - 1, $this->image_dst_y - $y - 1, 1, 1);
4178. } else if ($this->image_rotate == 270) {
4179. imagecopy($tmp, $image_dst, $y, $x, $this->image_dst_x - $x - 1, $y, 1, 1);
4180. } else {
4181. imagecopy($tmp, $image_dst, $x, $y, $x, $y, 1, 1);
4182. }
4183. }
4184. }
4185. if ($this->image_rotate == 90 || $this->image_rotate == 270) {
4186. $t = $this->image_dst_y;
4187. $this->image_dst_y = $this->image_dst_x;
4188. $this->image_dst_x = $t;
4189. }
4190. // we transfert tmp into image_dst
4191. $image_dst = $this->imagetransfer($tmp, $image_dst);
4192. }
4193. }
4195. // pixelate image
4196. if ((is_numeric($this->image_pixelate) && $this->image_pixelate > 0)) {
4197. $this->log .= '- pixelate image (' . $this->image_pixelate . 'px)<br />';
4198. $filter = $this->imagecreatenew($this->image_dst_x, $this->image_dst_y);
4199. if ($gd_version >= 2) {
4200. imagecopyresampled($filter, $image_dst, 0, 0, 0, 0, round($this->image_dst_x / $this->image_pixelate), round($this->image_dst_y / $this->image_pixelate), $this->image_dst_x, $this->image_dst_y);
4201. imagecopyresampled($image_dst, $filter, 0, 0, 0, 0, $this->image_dst_x, $this->image_dst_y, round($this->image_dst_x / $this->image_pixelate), round($this->image_dst_y / $this->image_pixelate));
4202. } else {
4203. imagecopyresized($filter, $image_dst, 0, 0, 0, 0, round($this->image_dst_x / $this->image_pixelate), round($this->image_dst_y / $this->image_pixelate), $this->image_dst_x, $this->image_dst_y);
4204. imagecopyresized($image_dst, $filter, 0, 0, 0, 0, $this->image_dst_x, $this->image_dst_y, round($this->image_dst_x / $this->image_pixelate), round($this->image_dst_y / $this->image_pixelate));
4205. }
4206. imagedestroy($filter);
4207. }
4209. // unsharp mask
4210. if ($gd_version >= 2 && $this->image_unsharp && is_numeric($this->image_unsharp_amount) && is_numeric($this->image_unsharp_radius) && is_numeric($this->image_unsharp_threshold)) {
4211. // Unsharp Mask for PHP - version 2.1.1
4212. // Unsharp mask algorithm by Torstein Hønsi 2003-07.
4213. // Used with permission
4214. // Modified to support alpha transparency
4215. if ($this->image_unsharp_amount > 500) $this->image_unsharp_amount = 500;
4216. $this->image_unsharp_amount = $this->image_unsharp_amount * 0.016;
4217. if ($this->image_unsharp_radius > 50) $this->image_unsharp_radius = 50;
4218. $this->image_unsharp_radius = $this->image_unsharp_radius * 2;
4219. if ($this->image_unsharp_threshold > 255) $this->image_unsharp_threshold = 255;
4220. $this->image_unsharp_radius = abs(round($this->image_unsharp_radius));
4221. if ($this->image_unsharp_radius != 0) {
4222. $this->image_dst_x = imagesx($image_dst); $this->image_dst_y = imagesy($image_dst);
4223. $canvas = $this->imagecreatenew($this->image_dst_x, $this->image_dst_y, false, true);
4224. $blur = $this->imagecreatenew($this->image_dst_x, $this->image_dst_y, false, true);
4225. if (function_exists('imageconvolution')) { // PHP >= 5.1
4226. $matrix = array(array( 1, 2, 1 ), array( 2, 4, 2 ), array( 1, 2, 1 ));
4227. imagecopy($blur, $image_dst, 0, 0, 0, 0, $this->image_dst_x, $this->image_dst_y);
4228. imageconvolution($blur, $matrix, 16, 0);
4229. } else {
4230. for ($i = 0; $i < $this->image_unsharp_radius; $i++) {
4231. imagecopy($blur, $image_dst, 0, 0, 1, 0, $this->image_dst_x - 1, $this->image_dst_y); // left
4232. $this->imagecopymergealpha($blur, $image_dst, 1, 0, 0, 0, $this->image_dst_x, $this->image_dst_y, 50); // right
4233. $this->imagecopymergealpha($blur, $image_dst, 0, 0, 0, 0, $this->image_dst_x, $this->image_dst_y, 50); // center
4234. imagecopy($canvas, $blur, 0, 0, 0, 0, $this->image_dst_x, $this->image_dst_y);
4235. $this->imagecopymergealpha($blur, $canvas, 0, 0, 0, 1, $this->image_dst_x, $this->image_dst_y - 1, 33.33333 ); // up
4236. $this->imagecopymergealpha($blur, $canvas, 0, 1, 0, 0, $this->image_dst_x, $this->image_dst_y, 25); // down
4237. }
4238. }
4239. $p_new = array();
4240. if($this->image_unsharp_threshold>0) {
4241. for ($x = 0; $x < $this->image_dst_x-1; $x++) {
4242. for ($y = 0; $y < $this->image_dst_y; $y++) {
4243. $p_orig = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y));
4244. $p_blur = imagecolorsforindex($blur, imagecolorat($blur, $x, $y));
4245. $p_new['red'] = (abs($p_orig['red'] - $p_blur['red']) >= $this->image_unsharp_threshold) ? max(0, min(255, ($this->image_unsharp_amount * ($p_orig['red'] - $p_blur['red'])) + $p_orig['red'])) : $p_orig['red'];
4246. $p_new['green'] = (abs($p_orig['green'] - $p_blur['green']) >= $this->image_unsharp_threshold) ? max(0, min(255, ($this->image_unsharp_amount * ($p_orig['green'] - $p_blur['green'])) + $p_orig['green'])) : $p_orig['green'];
4247. $p_new['blue'] = (abs($p_orig['blue'] - $p_blur['blue']) >= $this->image_unsharp_threshold) ? max(0, min(255, ($this->image_unsharp_amount * ($p_orig['blue'] - $p_blur['blue'])) + $p_orig['blue'])) : $p_orig['blue'];
4248. if (($p_orig['red'] != $p_new['red']) || ($p_orig['green'] != $p_new['green']) || ($p_orig['blue'] != $p_new['blue'])) {
4249. $color = imagecolorallocatealpha($image_dst, $p_new['red'], $p_new['green'], $p_new['blue'], $p_orig['alpha']);
4250. imagesetpixel($image_dst, $x, $y, $color);
4251. }
4252. }
4253. }
4254. } else {
4255. for ($x = 0; $x < $this->image_dst_x; $x++) {
4256. for ($y = 0; $y < $this->image_dst_y; $y++) {
4257. $p_orig = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y));
4258. $p_blur = imagecolorsforindex($blur, imagecolorat($blur, $x, $y));
4259. $p_new['red'] = ($this->image_unsharp_amount * ($p_orig['red'] - $p_blur['red'])) + $p_orig['red'];
4260. if ($p_new['red']>255) { $p_new['red']=255; } elseif ($p_new['red']<0) { $p_new['red']=0; }
4261. $p_new['green'] = ($this->image_unsharp_amount * ($p_orig['green'] - $p_blur['green'])) + $p_orig['green'];
4262. if ($p_new['green']>255) { $p_new['green']=255; } elseif ($p_new['green']<0) { $p_new['green']=0; }
4263. $p_new['blue'] = ($this->image_unsharp_amount * ($p_orig['blue'] - $p_blur['blue'])) + $p_orig['blue'];
4264. if ($p_new['blue']>255) { $p_new['blue']=255; } elseif ($p_new['blue']<0) { $p_new['blue']=0; }
4265. $color = imagecolorallocatealpha($image_dst, $p_new['red'], $p_new['green'], $p_new['blue'], $p_orig['alpha']);
4266. imagesetpixel($image_dst, $x, $y, $color);
4267. }
4268. }
4269. }
4270. imagedestroy($canvas);
4271. imagedestroy($blur);
4272. }
4273. }
4275. // add color overlay
4276. if ($gd_version >= 2 && (is_numeric($this->image_overlay_opacity) && $this->image_overlay_opacity > 0 && !empty($this->image_overlay_color))) {
4277. $this->log .= '- apply color overlay<br />';
4278. list($red, $green, $blue) = $this->getcolors($this->image_overlay_color);
4279. $filter = imagecreatetruecolor($this->image_dst_x, $this->image_dst_y);
4280. $color = imagecolorallocate($filter, $red, $green, $blue);
4281. imagefilledrectangle($filter, 0, 0, $this->image_dst_x, $this->image_dst_y, $color);
4282. $this->imagecopymergealpha($image_dst, $filter, 0, 0, 0, 0, $this->image_dst_x, $this->image_dst_y, $this->image_overlay_opacity);
4283. imagedestroy($filter);
4284. }
4286. // add brightness, contrast and tint, turns to greyscale and inverts colors
4287. if ($gd_version >= 2 && ($this->image_negative || $this->image_greyscale || is_numeric($this->image_threshold)|| is_numeric($this->image_brightness) || is_numeric($this->image_contrast) || !empty($this->image_tint_color))) {
4288. $this->log .= '- apply tint, light, contrast correction, negative, greyscale and threshold<br />';
4289. if (!empty($this->image_tint_color)) list($tint_red, $tint_green, $tint_blue) = $this->getcolors($this->image_tint_color);
4290. //imagealphablending($image_dst, true);
4291. for($y=0; $y < $this->image_dst_y; $y++) {
4292. for($x=0; $x < $this->image_dst_x; $x++) {
4293. if ($this->image_greyscale) {
4294. $pixel = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y));
4295. $r = $g = $b = round((0.2125 * $pixel['red']) + (0.7154 * $pixel['green']) + (0.0721 * $pixel['blue']));
4296. $color = imagecolorallocatealpha($image_dst, $r, $g, $b, $pixel['alpha']);
4297. imagesetpixel($image_dst, $x, $y, $color);
4298. unset($color); unset($pixel);
4299. }
4300. if (is_numeric($this->image_threshold)) {
4301. $pixel = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y));
4302. $c = (round($pixel['red'] + $pixel['green'] + $pixel['blue']) / 3) - 127;
4303. $r = $g = $b = ($c > $this->image_threshold ? 255 : 0);
4304. $color = imagecolorallocatealpha($image_dst, $r, $g, $b, $pixel['alpha']);
4305. imagesetpixel($image_dst, $x, $y, $color);
4306. unset($color); unset($pixel);
4307. }
4308. if (is_numeric($this->image_brightness)) {
4309. $pixel = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y));
4310. $r = max(min(round($pixel['red'] + (($this->image_brightness * 2))), 255), 0);
4311. $g = max(min(round($pixel['green'] + (($this->image_brightness * 2))), 255), 0);
4312. $b = max(min(round($pixel['blue'] + (($this->image_brightness * 2))), 255), 0);
4313. $color = imagecolorallocatealpha($image_dst, $r, $g, $b, $pixel['alpha']);
4314. imagesetpixel($image_dst, $x, $y, $color);
4315. unset($color); unset($pixel);
4316. }
4317. if (is_numeric($this->image_contrast)) {
4318. $pixel = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y));
4319. $r = max(min(round(($this->image_contrast + 128) * $pixel['red'] / 128), 255), 0);
4320. $g = max(min(round(($this->image_contrast + 128) * $pixel['green'] / 128), 255), 0);
4321. $b = max(min(round(($this->image_contrast + 128) * $pixel['blue'] / 128), 255), 0);
4322. $color = imagecolorallocatealpha($image_dst, $r, $g, $b, $pixel['alpha']);
4323. imagesetpixel($image_dst, $x, $y, $color);
4324. unset($color); unset($pixel);
4325. }
4326. if (!empty($this->image_tint_color)) {
4327. $pixel = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y));
4328. $r = min(round($tint_red * $pixel['red'] / 169), 255);
4329. $g = min(round($tint_green * $pixel['green'] / 169), 255);
4330. $b = min(round($tint_blue * $pixel['blue'] / 169), 255);
4331. $color = imagecolorallocatealpha($image_dst, $r, $g, $b, $pixel['alpha']);
4332. imagesetpixel($image_dst, $x, $y, $color);
4333. unset($color); unset($pixel);
4334. }
4335. if (!empty($this->image_negative)) {
4336. $pixel = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y));
4337. $r = round(255 - $pixel['red']);
4338. $g = round(255 - $pixel['green']);
4339. $b = round(255 - $pixel['blue']);
4340. $color = imagecolorallocatealpha($image_dst, $r, $g, $b, $pixel['alpha']);
4341. imagesetpixel($image_dst, $x, $y, $color);
4342. unset($color); unset($pixel);
4343. }
4344. }
4345. }
4346. }
4348. // adds a border
4349. if ($gd_version >= 2 && !empty($this->image_border)) {
4350. list($ct, $cr, $cb, $cl) = $this->getoffsets($this->image_border, $this->image_dst_x, $this->image_dst_y, true, false);
4351. $this->log .= '- add border : ' . $ct . ' ' . $cr . ' ' . $cb . ' ' . $cl . '<br />';
4352. $this->image_dst_x = $this->image_dst_x + $cl + $cr;
4353. $this->image_dst_y = $this->image_dst_y + $ct + $cb;
4354. if (!empty($this->image_border_color)) list($red, $green, $blue) = $this->getcolors($this->image_border_color);
4355. $opacity = (is_numeric($this->image_border_opacity) ? (int) (127 - $this->image_border_opacity / 100 * 127): 0);
4356. // we now create an image, that we fill with the border color
4357. $tmp = $this->imagecreatenew($this->image_dst_x, $this->image_dst_y);
4358. $background = imagecolorallocatealpha($tmp, $red, $green, $blue, $opacity);
4359. imagefilledrectangle($tmp, 0, 0, $this->image_dst_x, $this->image_dst_y, $background);
4360. // we then copy the source image into the new image, without merging so that only the border is actually kept
4361. imagecopy($tmp, $image_dst, $cl, $ct, 0, 0, $this->image_dst_x - $cr - $cl, $this->image_dst_y - $cb - $ct);
4362. // we transfert tmp into image_dst
4363. $image_dst = $this->imagetransfer($tmp, $image_dst);
4364. }
4366. // adds a fading-to-transparent border
4367. if ($gd_version >= 2 && !empty($this->image_border_transparent)) {
4368. list($ct, $cr, $cb, $cl) = $this->getoffsets($this->image_border_transparent, $this->image_dst_x, $this->image_dst_y, true, false);
4369. $this->log .= '- add transparent border : ' . $ct . ' ' . $cr . ' ' . $cb . ' ' . $cl . '<br />';
4370. // we now create an image, that we fill with the border color
4371. $tmp = $this->imagecreatenew($this->image_dst_x, $this->image_dst_y);
4372. // we then copy the source image into the new image, without the borders
4373. imagecopy($tmp, $image_dst, $cl, $ct, $cl, $ct, $this->image_dst_x - $cr - $cl, $this->image_dst_y - $cb - $ct);
4374. // we now add the top border
4375. $opacity = 100;
4376. for ($y = $ct - 1; $y >= 0; $y--) {
4377. $il = (int) ($ct > 0 ? ($cl * ($y / $ct)) : 0);
4378. $ir = (int) ($ct > 0 ? ($cr * ($y / $ct)) : 0);
4379. for ($x = $il; $x < $this->image_dst_x - $ir; $x++) {
4380. $pixel = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y));
4381. $alpha = (1 - ($pixel['alpha'] / 127)) * $opacity / 100;
4382. if ($alpha > 0) {
4383. if ($alpha > 1) $alpha = 1;
4384. $color = imagecolorallocatealpha($tmp, $pixel['red'] , $pixel['green'], $pixel['blue'], round((1 - $alpha) * 127));
4385. imagesetpixel($tmp, $x, $y, $color);
4386. }
4387. }
4388. if ($opacity > 0) $opacity = $opacity - (100 / $ct);
4389. }
4390. // we now add the right border
4391. $opacity = 100;
4392. for ($x = $this->image_dst_x - $cr; $x < $this->image_dst_x; $x++) {
4393. $it = (int) ($cr > 0 ? ($ct * (($this->image_dst_x - $x - 1) / $cr)) : 0);
4394. $ib = (int) ($cr > 0 ? ($cb * (($this->image_dst_x - $x - 1) / $cr)) : 0);
4395. for ($y = $it; $y < $this->image_dst_y - $ib; $y++) {
4396. $pixel = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y));
4397. $alpha = (1 - ($pixel['alpha'] / 127)) * $opacity / 100;
4398. if ($alpha > 0) {
4399. if ($alpha > 1) $alpha = 1;
4400. $color = imagecolorallocatealpha($tmp, $pixel['red'] , $pixel['green'], $pixel['blue'], round((1 - $alpha) * 127));
4401. imagesetpixel($tmp, $x, $y, $color);
4402. }
4403. }
4404. if ($opacity > 0) $opacity = $opacity - (100 / $cr);
4405. }
4406. // we now add the bottom border
4407. $opacity = 100;
4408. for ($y = $this->image_dst_y - $cb; $y < $this->image_dst_y; $y++) {
4409. $il = (int) ($cb > 0 ? ($cl * (($this->image_dst_y - $y - 1) / $cb)) : 0);
4410. $ir = (int) ($cb > 0 ? ($cr * (($this->image_dst_y - $y - 1) / $cb)) : 0);
4411. for ($x = $il; $x < $this->image_dst_x - $ir; $x++) {
4412. $pixel = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y));
4413. $alpha = (1 - ($pixel['alpha'] / 127)) * $opacity / 100;
4414. if ($alpha > 0) {
4415. if ($alpha > 1) $alpha = 1;
4416. $color = imagecolorallocatealpha($tmp, $pixel['red'] , $pixel['green'], $pixel['blue'], round((1 - $alpha) * 127));
4417. imagesetpixel($tmp, $x, $y, $color);
4418. }
4419. }
4420. if ($opacity > 0) $opacity = $opacity - (100 / $cb);
4421. }
4422. // we now add the left border
4423. $opacity = 100;
4424. for ($x = $cl - 1; $x >= 0; $x--) {
4425. $it = (int) ($cl > 0 ? ($ct * ($x / $cl)) : 0);
4426. $ib = (int) ($cl > 0 ? ($cb * ($x / $cl)) : 0);
4427. for ($y = $it; $y < $this->image_dst_y - $ib; $y++) {
4428. $pixel = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y));
4429. $alpha = (1 - ($pixel['alpha'] / 127)) * $opacity / 100;
4430. if ($alpha > 0) {
4431. if ($alpha > 1) $alpha = 1;
4432. $color = imagecolorallocatealpha($tmp, $pixel['red'] , $pixel['green'], $pixel['blue'], round((1 - $alpha) * 127));
4433. imagesetpixel($tmp, $x, $y, $color);
4434. }
4435. }
4436. if ($opacity > 0) $opacity = $opacity - (100 / $cl);
4437. }
4438. // we transfert tmp into image_dst
4439. $image_dst = $this->imagetransfer($tmp, $image_dst);
4440. }
4442. // add frame border
4443. if ($gd_version >= 2 && is_numeric($this->image_frame)) {
4444. if (is_array($this->image_frame_colors)) {
4445. $vars = $this->image_frame_colors;
4446. $this->log .= '- add frame : ' . implode(' ', $this->image_frame_colors) . '<br />';
4447. } else {
4448. $this->log .= '- add frame : ' . $this->image_frame_colors . '<br />';
4449. $vars = explode(' ', $this->image_frame_colors);
4450. }
4451. $nb = sizeof($vars);
4452. $this->image_dst_x = $this->image_dst_x + ($nb * 2);
4453. $this->image_dst_y = $this->image_dst_y + ($nb * 2);
4454. $tmp = $this->imagecreatenew($this->image_dst_x, $this->image_dst_y);
4455. imagecopy($tmp, $image_dst, $nb, $nb, 0, 0, $this->image_dst_x - ($nb * 2), $this->image_dst_y - ($nb * 2));
4456. $opacity = (is_numeric($this->image_frame_opacity) ? (int) (127 - $this->image_frame_opacity / 100 * 127): 0);
4457. for ($i=0; $i<$nb; $i++) {
4458. list($red, $green, $blue) = $this->getcolors($vars[$i]);
4459. $c = imagecolorallocatealpha($tmp, $red, $green, $blue, $opacity);
4460. if ($this->image_frame == 1) {
4461. imageline($tmp, $i, $i, $this->image_dst_x - $i -1, $i, $c);
4462. imageline($tmp, $this->image_dst_x - $i -1, $this->image_dst_y - $i -1, $this->image_dst_x - $i -1, $i, $c);
4463. imageline($tmp, $this->image_dst_x - $i -1, $this->image_dst_y - $i -1, $i, $this->image_dst_y - $i -1, $c);
4464. imageline($tmp, $i, $i, $i, $this->image_dst_y - $i -1, $c);
4465. } else {
4466. imageline($tmp, $i, $i, $this->image_dst_x - $i -1, $i, $c);
4467. imageline($tmp, $this->image_dst_x - $nb + $i, $this->image_dst_y - $nb + $i, $this->image_dst_x - $nb + $i, $nb - $i, $c);
4468. imageline($tmp, $this->image_dst_x - $nb + $i, $this->image_dst_y - $nb + $i, $nb - $i, $this->image_dst_y - $nb + $i, $c);
4469. imageline($tmp, $i, $i, $i, $this->image_dst_y - $i -1, $c);
4470. }
4471. }
4472. // we transfert tmp into image_dst
4473. $image_dst = $this->imagetransfer($tmp, $image_dst);
4474. }
4476. // add bevel border
4477. if ($gd_version >= 2 && $this->image_bevel > 0) {
4478. if (empty($this->image_bevel_color1)) $this->image_bevel_color1 = '#FFFFFF';
4479. if (empty($this->image_bevel_color2)) $this->image_bevel_color2 = '#000000';
4480. list($red1, $green1, $blue1) = $this->getcolors($this->image_bevel_color1);
4481. list($red2, $green2, $blue2) = $this->getcolors($this->image_bevel_color2);
4482. $tmp = $this->imagecreatenew($this->image_dst_x, $this->image_dst_y);
4483. imagecopy($tmp, $image_dst, 0, 0, 0, 0, $this->image_dst_x, $this->image_dst_y);
4484. imagealphablending($tmp, true);
4485. for ($i=0; $i<$this->image_bevel; $i++) {
4486. $alpha = round(($i / $this->image_bevel) * 127);
4487. $c1 = imagecolorallocatealpha($tmp, $red1, $green1, $blue1, $alpha);
4488. $c2 = imagecolorallocatealpha($tmp, $red2, $green2, $blue2, $alpha);
4489. imageline($tmp, $i, $i, $this->image_dst_x - $i -1, $i, $c1);
4490. imageline($tmp, $this->image_dst_x - $i -1, $this->image_dst_y - $i, $this->image_dst_x - $i -1, $i, $c2);
4491. imageline($tmp, $this->image_dst_x - $i -1, $this->image_dst_y - $i -1, $i, $this->image_dst_y - $i -1, $c2);
4492. imageline($tmp, $i, $i, $i, $this->image_dst_y - $i -1, $c1);
4493. }
4494. // we transfert tmp into image_dst
4495. $image_dst = $this->imagetransfer($tmp, $image_dst);
4496. }
4498. // add watermark image
4499. if ($this->image_watermark!='' && file_exists($this->image_watermark)) {
4500. $this->log .= '- add watermark<br />';
4501. $this->image_watermark_position = strtolower($this->image_watermark_position);
4502. $watermark_info = getimagesize($this->image_watermark);
4503. $watermark_type = (array_key_exists(2, $watermark_info) ? $watermark_info[2] : null); // 1 = GIF, 2 = JPG, 3 = PNG
4504. $watermark_checked = false;
4505. if ($watermark_type == IMAGETYPE_GIF) {
4506. if (!function_exists('imagecreatefromgif')) {
4507. $this->error = $this->translate('watermark_no_create_support', array('GIF'));
4508. } else {
4509. $filter = @imagecreatefromgif($this->image_watermark);
4510. if (!$filter) {
4511. $this->error = $this->translate('watermark_create_error', array('GIF'));
4512. } else {
4513. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;watermark source image is GIF<br />';
4514. $watermark_checked = true;
4515. }
4516. }
4517. } else if ($watermark_type == IMAGETYPE_JPEG) {
4518. if (!function_exists('imagecreatefromjpeg')) {
4519. $this->error = $this->translate('watermark_no_create_support', array('JPEG'));
4520. } else {
4521. $filter = @imagecreatefromjpeg($this->image_watermark);
4522. if (!$filter) {
4523. $this->error = $this->translate('watermark_create_error', array('JPEG'));
4524. } else {
4525. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;watermark source image is JPEG<br />';
4526. $watermark_checked = true;
4527. }
4528. }
4529. } else if ($watermark_type == IMAGETYPE_PNG) {
4530. if (!function_exists('imagecreatefrompng')) {
4531. $this->error = $this->translate('watermark_no_create_support', array('PNG'));
4532. } else {
4533. $filter = @imagecreatefrompng($this->image_watermark);
4534. if (!$filter) {
4535. $this->error = $this->translate('watermark_create_error', array('PNG'));
4536. } else {
4537. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;watermark source image is PNG<br />';
4538. $watermark_checked = true;
4539. }
4540. }
4541. } else if ($watermark_type == IMAGETYPE_BMP) {
4542. if (!method_exists($this, 'imagecreatefrombmp')) {
4543. $this->error = $this->translate('watermark_no_create_support', array('BMP'));
4544. } else {
4545. $filter = @$this->imagecreatefrombmp($this->image_watermark);
4546. if (!$filter) {
4547. $this->error = $this->translate('watermark_create_error', array('BMP'));
4548. } else {
4549. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;watermark source image is BMP<br />';
4550. $watermark_checked = true;
4551. }
4552. }
4553. } else {
4554. $this->error = $this->translate('watermark_invalid');
4555. }
4556. if ($watermark_checked) {
4557. $watermark_dst_width = $watermark_src_width = imagesx($filter);
4558. $watermark_dst_height = $watermark_src_height = imagesy($filter);
4560. // if watermark is too large/tall, resize it first
4561. if ((!$this->image_watermark_no_zoom_out && ($watermark_dst_width > $this->image_dst_x || $watermark_dst_height > $this->image_dst_y))
4562. || (!$this->image_watermark_no_zoom_in && $watermark_dst_width < $this->image_dst_x && $watermark_dst_height < $this->image_dst_y)) {
4563. $canvas_width = $this->image_dst_x - abs($this->image_watermark_x);
4564. $canvas_height = $this->image_dst_y - abs($this->image_watermark_y);
4565. if (($watermark_src_width/$canvas_width) > ($watermark_src_height/$canvas_height)) {
4566. $watermark_dst_width = $canvas_width;
4567. $watermark_dst_height = intval($watermark_src_height*($canvas_width / $watermark_src_width));
4568. } else {
4569. $watermark_dst_height = $canvas_height;
4570. $watermark_dst_width = intval($watermark_src_width*($canvas_height / $watermark_src_height));
4571. }
4572. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;watermark resized from '.$watermark_src_width.'x'.$watermark_src_height.' to '.$watermark_dst_width.'x'.$watermark_dst_height.'<br />';
4574. }
4575. // determine watermark position
4576. $watermark_x = 0;
4577. $watermark_y = 0;
4578. if (is_numeric($this->image_watermark_x)) {
4579. if ($this->image_watermark_x < 0) {
4580. $watermark_x = $this->image_dst_x - $watermark_dst_width + $this->image_watermark_x;
4581. } else {
4582. $watermark_x = $this->image_watermark_x;
4583. }
4584. } else {
4585. if (strpos($this->image_watermark_position, 'r') !== false) {
4586. $watermark_x = $this->image_dst_x - $watermark_dst_width;
4587. } else if (strpos($this->image_watermark_position, 'l') !== false) {
4588. $watermark_x = 0;
4589. } else {
4590. $watermark_x = ($this->image_dst_x - $watermark_dst_width) / 2;
4591. }
4592. }
4593. if (is_numeric($this->image_watermark_y)) {
4594. if ($this->image_watermark_y < 0) {
4595. $watermark_y = $this->image_dst_y - $watermark_dst_height + $this->image_watermark_y;
4596. } else {
4597. $watermark_y = $this->image_watermark_y;
4598. }
4599. } else {
4600. if (strpos($this->image_watermark_position, 'b') !== false) {
4601. $watermark_y = $this->image_dst_y - $watermark_dst_height;
4602. } else if (strpos($this->image_watermark_position, 't') !== false) {
4603. $watermark_y = 0;
4604. } else {
4605. $watermark_y = ($this->image_dst_y - $watermark_dst_height) / 2;
4606. }
4607. }
4608. imagealphablending($image_dst, true);
4609. imagecopyresampled($image_dst, $filter, $watermark_x, $watermark_y, 0, 0, $watermark_dst_width, $watermark_dst_height, $watermark_src_width, $watermark_src_height);
4610. } else {
4611. $this->error = $this->translate('watermark_invalid');
4612. }
4613. }
4615. // add text
4616. if (!empty($this->image_text)) {
4617. $this->log .= '- add text<br />';
4619. // calculate sizes in human readable format
4620. $src_size = $this->file_src_size / 1024;
4621. $src_size_mb = number_format($src_size / 1024, 1, ".", " ");
4622. $src_size_kb = number_format($src_size, 1, ".", " ");
4623. $src_size_human = ($src_size > 1024 ? $src_size_mb . " MB" : $src_size_kb . " kb");
4625. $this->image_text = str_replace(
4626. array('[src_name]',
4627. '[src_name_body]',
4628. '[src_name_ext]',
4629. '[src_pathname]',
4630. '[src_mime]',
4631. '[src_size]',
4632. '[src_size_kb]',
4633. '[src_size_mb]',
4634. '[src_size_human]',
4635. '[src_x]',
4636. '[src_y]',
4637. '[src_pixels]',
4638. '[src_type]',
4639. '[src_bits]',
4640. '[dst_path]',
4641. '[dst_name_body]',
4642. '[dst_name_ext]',
4643. '[dst_name]',
4644. '[dst_pathname]',
4645. '[dst_x]',
4646. '[dst_y]',
4647. '[date]',
4648. '[time]',
4649. '[host]',
4650. '[server]',
4651. '[ip]',
4652. '[gd_version]'),
4653. array($this->file_src_name,
4654. $this->file_src_name_body,
4655. $this->file_src_name_ext,
4656. $this->file_src_pathname,
4657. $this->file_src_mime,
4658. $this->file_src_size,
4659. $src_size_kb,
4660. $src_size_mb,
4661. $src_size_human,
4662. $this->image_src_x,
4663. $this->image_src_y,
4664. $this->image_src_pixels,
4665. $this->image_src_type,
4666. $this->image_src_bits,
4667. $this->file_dst_path,
4668. $this->file_dst_name_body,
4669. $this->file_dst_name_ext,
4670. $this->file_dst_name,
4671. $this->file_dst_pathname,
4672. $this->image_dst_x,
4673. $this->image_dst_y,
4674. date('Y-m-d'),
4675. date('H:i:s'),
4676. (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : 'n/a'),
4677. (isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : 'n/a'),
4678. (isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : 'n/a'),
4679. $this->gdversion(true)),
4680. $this->image_text);
4682. if (!is_numeric($this->image_text_padding)) $this->image_text_padding = 0;
4683. if (!is_numeric($this->image_text_line_spacing)) $this->image_text_line_spacing = 0;
4684. if (!is_numeric($this->image_text_padding_x)) $this->image_text_padding_x = $this->image_text_padding;
4685. if (!is_numeric($this->image_text_padding_y)) $this->image_text_padding_y = $this->image_text_padding;
4686. $this->image_text_position = strtolower($this->image_text_position);
4687. $this->image_text_direction = strtolower($this->image_text_direction);
4688. $this->image_text_alignment = strtolower($this->image_text_alignment);
4690. // if the font is a string, we assume that we might want to load a font
4691. if (!is_numeric($this->image_text_font) && strlen($this->image_text_font) > 4 && substr(strtolower($this->image_text_font), -4) == '.gdf') {
4692. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;try to load font ' . $this->image_text_font . '... ';
4693. if ($this->image_text_font = @imageloadfont($this->image_text_font)) {
4694. $this->log .= 'success<br />';
4695. } else {
4696. $this->log .= 'error<br />';
4697. $this->image_text_font = 5;
4698. }
4699. }
4701. $text = explode("\n", $this->image_text);
4702. $char_width = imagefontwidth($this->image_text_font);
4703. $char_height = imagefontheight($this->image_text_font);
4704. $text_height = 0;
4705. $text_width = 0;
4706. $line_height = 0;
4707. $line_width = 0;
4709. foreach ($text as $k => $v) {
4710. if ($this->image_text_direction == 'v') {
4711. $h = ($char_width * strlen($v));
4712. if ($h > $text_height) $text_height = $h;
4713. $line_width = $char_height;
4714. $text_width += $line_width + ($k < (sizeof($text)-1) ? $this->image_text_line_spacing : 0);
4715. } else {
4716. $w = ($char_width * strlen($v));
4717. if ($w > $text_width) $text_width = $w;
4718. $line_height = $char_height;
4719. $text_height += $line_height + ($k < (sizeof($text)-1) ? $this->image_text_line_spacing : 0);
4720. }
4721. }
4722. $text_width += (2 * $this->image_text_padding_x);
4723. $text_height += (2 * $this->image_text_padding_y);
4724. $text_x = 0;
4725. $text_y = 0;
4726. if (is_numeric($this->image_text_x)) {
4727. if ($this->image_text_x < 0) {
4728. $text_x = $this->image_dst_x - $text_width + $this->image_text_x;
4729. } else {
4730. $text_x = $this->image_text_x;
4731. }
4732. } else {
4733. if (strpos($this->image_text_position, 'r') !== false) {
4734. $text_x = $this->image_dst_x - $text_width;
4735. } else if (strpos($this->image_text_position, 'l') !== false) {
4736. $text_x = 0;
4737. } else {
4738. $text_x = ($this->image_dst_x - $text_width) / 2;
4739. }
4740. }
4741. if (is_numeric($this->image_text_y)) {
4742. if ($this->image_text_y < 0) {
4743. $text_y = $this->image_dst_y - $text_height + $this->image_text_y;
4744. } else {
4745. $text_y = $this->image_text_y;
4746. }
4747. } else {
4748. if (strpos($this->image_text_position, 'b') !== false) {
4749. $text_y = $this->image_dst_y - $text_height;
4750. } else if (strpos($this->image_text_position, 't') !== false) {
4751. $text_y = 0;
4752. } else {
4753. $text_y = ($this->image_dst_y - $text_height) / 2;
4754. }
4755. }
4757. // add a background, maybe transparent
4758. if (!empty($this->image_text_background)) {
4759. list($red, $green, $blue) = $this->getcolors($this->image_text_background);
4760. if ($gd_version >= 2 && (is_numeric($this->image_text_background_opacity)) && $this->image_text_background_opacity >= 0 && $this->image_text_background_opacity <= 100) {
4761. $filter = imagecreatetruecolor($text_width, $text_height);
4762. $background_color = imagecolorallocate($filter, $red, $green, $blue);
4763. imagefilledrectangle($filter, 0, 0, $text_width, $text_height, $background_color);
4764. $this->imagecopymergealpha($image_dst, $filter, $text_x, $text_y, 0, 0, $text_width, $text_height, $this->image_text_background_opacity);
4765. imagedestroy($filter);
4766. } else {
4767. $background_color = imagecolorallocate($image_dst ,$red, $green, $blue);
4768. imagefilledrectangle($image_dst, $text_x, $text_y, $text_x + $text_width, $text_y + $text_height, $background_color);
4769. }
4770. }
4772. $text_x += $this->image_text_padding_x;
4773. $text_y += $this->image_text_padding_y;
4774. $t_width = $text_width - (2 * $this->image_text_padding_x);
4775. $t_height = $text_height - (2 * $this->image_text_padding_y);
4776. list($red, $green, $blue) = $this->getcolors($this->image_text_color);
4778. // add the text, maybe transparent
4779. if ($gd_version >= 2 && (is_numeric($this->image_text_opacity)) && $this->image_text_opacity >= 0 && $this->image_text_opacity <= 100) {
4780. if ($t_width < 0) $t_width = 0;
4781. if ($t_height < 0) $t_height = 0;
4782. $filter = $this->imagecreatenew($t_width, $t_height, false, true);
4783. $text_color = imagecolorallocate($filter ,$red, $green, $blue);
4785. foreach ($text as $k => $v) {
4786. if ($this->image_text_direction == 'v') {
4787. imagestringup($filter,
4788. $this->image_text_font,
4789. $k * ($line_width + ($k > 0 && $k < (sizeof($text)) ? $this->image_text_line_spacing : 0)),
4790. $text_height - (2 * $this->image_text_padding_y) - ($this->image_text_alignment == 'l' ? 0 : (($t_height - strlen($v) * $char_width) / ($this->image_text_alignment == 'r' ? 1 : 2))) ,
4791. $v,
4792. $text_color);
4793. } else {
4794. imagestring($filter,
4795. $this->image_text_font,
4796. ($this->image_text_alignment == 'l' ? 0 : (($t_width - strlen($v) * $char_width) / ($this->image_text_alignment == 'r' ? 1 : 2))),
4797. $k * ($line_height + ($k > 0 && $k < (sizeof($text)) ? $this->image_text_line_spacing : 0)),
4798. $v,
4799. $text_color);
4800. }
4801. }
4802. $this->imagecopymergealpha($image_dst, $filter, $text_x, $text_y, 0, 0, $t_width, $t_height, $this->image_text_opacity);
4803. imagedestroy($filter);
4805. } else {
4806. $text_color = imageColorAllocate($image_dst ,$red, $green, $blue);
4807. foreach ($text as $k => $v) {
4808. if ($this->image_text_direction == 'v') {
4809. imagestringup($image_dst,
4810. $this->image_text_font,
4811. $text_x + $k * ($line_width + ($k > 0 && $k < (sizeof($text)) ? $this->image_text_line_spacing : 0)),
4812. $text_y + $text_height - (2 * $this->image_text_padding_y) - ($this->image_text_alignment == 'l' ? 0 : (($t_height - strlen($v) * $char_width) / ($this->image_text_alignment == 'r' ? 1 : 2))),
4813. $v,
4814. $text_color);
4815. } else {
4816. imagestring($image_dst,
4817. $this->image_text_font,
4818. $text_x + ($this->image_text_alignment == 'l' ? 0 : (($t_width - strlen($v) * $char_width) / ($this->image_text_alignment == 'r' ? 1 : 2))),
4819. $text_y + $k * ($line_height + ($k > 0 && $k < (sizeof($text)) ? $this->image_text_line_spacing : 0)),
4820. $v,
4821. $text_color);
4822. }
4823. }
4824. }
4825. }
4827. // add a reflection
4828. if ($this->image_reflection_height) {
4829. $this->log .= '- add reflection : ' . $this->image_reflection_height . '<br />';
4830. // we decode image_reflection_height, which can be a integer, a string in pixels or percentage
4831. $image_reflection_height = $this->image_reflection_height;
4832. if (strpos($image_reflection_height, '%')>0) $image_reflection_height = $this->image_dst_y * (str_replace('%','',$image_reflection_height / 100));
4833. if (strpos($image_reflection_height, 'px')>0) $image_reflection_height = str_replace('px','',$image_reflection_height);
4834. $image_reflection_height = (int) $image_reflection_height;
4835. if ($image_reflection_height > $this->image_dst_y) $image_reflection_height = $this->image_dst_y;
4836. if (empty($this->image_reflection_opacity)) $this->image_reflection_opacity = 60;
4837. // create the new destination image
4838. $tmp = $this->imagecreatenew($this->image_dst_x, $this->image_dst_y + $image_reflection_height + $this->image_reflection_space, true);
4839. $transparency = $this->image_reflection_opacity;
4841. // copy the original image
4842. imagecopy($tmp, $image_dst, 0, 0, 0, 0, $this->image_dst_x, $this->image_dst_y + ($this->image_reflection_space < 0 ? $this->image_reflection_space : 0));
4844. // we have to make sure the extra bit is the right color, or transparent
4845. if ($image_reflection_height + $this->image_reflection_space > 0) {
4846. // use the background color if present
4847. if (!empty($this->image_background_color)) {
4848. list($red, $green, $blue) = $this->getcolors($this->image_background_color);
4849. $fill = imagecolorallocate($tmp, $red, $green, $blue);
4850. } else {
4851. $fill = imagecolorallocatealpha($tmp, 0, 0, 0, 127);
4852. }
4853. // fill in from the edge of the extra bit
4854. imagefill($tmp, round($this->image_dst_x / 2), $this->image_dst_y + $image_reflection_height + $this->image_reflection_space - 1, $fill);
4855. }
4857. // copy the reflection
4858. for ($y = 0; $y < $image_reflection_height; $y++) {
4859. for ($x = 0; $x < $this->image_dst_x; $x++) {
4860. $pixel_b = imagecolorsforindex($tmp, imagecolorat($tmp, $x, $y + $this->image_dst_y + $this->image_reflection_space));
4861. $pixel_o = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $this->image_dst_y - $y - 1 + ($this->image_reflection_space < 0 ? $this->image_reflection_space : 0)));
4862. $alpha_o = 1 - ($pixel_o['alpha'] / 127);
4863. $alpha_b = 1 - ($pixel_b['alpha'] / 127);
4864. $opacity = $alpha_o * $transparency / 100;
4865. if ($opacity > 0) {
4866. $red = round((($pixel_o['red'] * $opacity) + ($pixel_b['red'] ) * $alpha_b) / ($alpha_b + $opacity));
4867. $green = round((($pixel_o['green'] * $opacity) + ($pixel_b['green']) * $alpha_b) / ($alpha_b + $opacity));
4868. $blue = round((($pixel_o['blue'] * $opacity) + ($pixel_b['blue'] ) * $alpha_b) / ($alpha_b + $opacity));
4869. $alpha = ($opacity + $alpha_b);
4870. if ($alpha > 1) $alpha = 1;
4871. $alpha = round((1 - $alpha) * 127);
4872. $color = imagecolorallocatealpha($tmp, $red, $green, $blue, $alpha);
4873. imagesetpixel($tmp, $x, $y + $this->image_dst_y + $this->image_reflection_space, $color);
4874. }
4875. }
4876. if ($transparency > 0) $transparency = $transparency - ($this->image_reflection_opacity / $image_reflection_height);
4877. }
4879. // copy the resulting image into the destination image
4880. $this->image_dst_y = $this->image_dst_y + $image_reflection_height + $this->image_reflection_space;
4881. $image_dst = $this->imagetransfer($tmp, $image_dst);
4882. }
4884. // change opacity
4885. if ($gd_version >= 2 && is_numeric($this->image_opacity) && $this->image_opacity < 100) {
4886. $this->log .= '- change opacity<br />';
4887. // create the new destination image
4888. $tmp = $this->imagecreatenew($this->image_dst_x, $this->image_dst_y, true);
4889. for($y=0; $y < $this->image_dst_y; $y++) {
4890. for($x=0; $x < $this->image_dst_x; $x++) {
4891. $pixel = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y));
4892. $alpha = $pixel['alpha'] + round((127 - $pixel['alpha']) * (100 - $this->image_opacity) / 100);
4893. if ($alpha > 127) $alpha = 127;
4894. if ($alpha > 0) {
4895. $color = imagecolorallocatealpha($tmp, $pixel['red'] , $pixel['green'], $pixel['blue'], $alpha);
4896. imagesetpixel($tmp, $x, $y, $color);
4897. }
4898. }
4899. }
4900. // copy the resulting image into the destination image
4901. $image_dst = $this->imagetransfer($tmp, $image_dst);
4902. }
4904. // reduce the JPEG image to a set desired size
4905. if (is_numeric($this->jpeg_size) && $this->jpeg_size > 0 && ($this->image_convert == 'jpeg' || $this->image_convert == 'jpg')) {
4906. // inspired by: JPEGReducer class version 1, 25 November 2004, Author: Huda M ElMatsani, justhuda at netscape dot net
4907. $this->log .= '- JPEG desired file size : ' . $this->jpeg_size . '<br />';
4908. // calculate size of each image. 75%, 50%, and 25% quality
4909. ob_start(); imagejpeg($image_dst,null,75); $buffer = ob_get_contents(); ob_end_clean();
4910. $size75 = strlen($buffer);
4911. ob_start(); imagejpeg($image_dst,null,50); $buffer = ob_get_contents(); ob_end_clean();
4912. $size50 = strlen($buffer);
4913. ob_start(); imagejpeg($image_dst,null,25); $buffer = ob_get_contents(); ob_end_clean();
4914. $size25 = strlen($buffer);
4916. // make sure we won't divide by 0
4917. if ($size50 == $size25) $size50++;
4918. if ($size75 == $size50 || $size75 == $size25) $size75++;
4920. // calculate gradient of size reduction by quality
4921. $mgrad1 = 25 / ($size50-$size25);
4922. $mgrad2 = 25 / ($size75-$size50);
4923. $mgrad3 = 50 / ($size75-$size25);
4924. $mgrad = ($mgrad1 + $mgrad2 + $mgrad3) / 3;
4925. // result of approx. quality factor for expected size
4926. $q_factor = round($mgrad * ($this->jpeg_size - $size50) + 50);
4928. if ($q_factor<1) {
4929. $this->jpeg_quality=1;
4930. } elseif ($q_factor>100) {
4931. $this->jpeg_quality=100;
4932. } else {
4933. $this->jpeg_quality=$q_factor;
4934. }
4935. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;JPEG quality factor set to ' . $this->jpeg_quality . '<br />';
4936. }
4938. // converts image from true color, and fix transparency if needed
4939. $this->log .= '- converting...<br />';
4940. switch($this->image_convert) {
4941. case 'gif':
4942. // if the image is true color, we convert it to a palette
4943. if (imageistruecolor($image_dst)) {
4944. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;true color to palette<br />';
4945. // creates a black and white mask
4946. $mask = array(array());
4947. for ($x = 0; $x < $this->image_dst_x; $x++) {
4948. for ($y = 0; $y < $this->image_dst_y; $y++) {
4949. $pixel = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y));
4950. $mask[$x][$y] = $pixel['alpha'];
4951. }
4952. }
4953. list($red, $green, $blue) = $this->getcolors($this->image_default_color);
4954. // first, we merge the image with the background color, so we know which colors we will have
4955. for ($x = 0; $x < $this->image_dst_x; $x++) {
4956. for ($y = 0; $y < $this->image_dst_y; $y++) {
4957. if ($mask[$x][$y] > 0){
4958. // we have some transparency. we combine the color with the default color
4959. $pixel = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y));
4960. $alpha = ($mask[$x][$y] / 127);
4961. $pixel['red'] = round(($pixel['red'] * (1 -$alpha) + $red * ($alpha)));
4962. $pixel['green'] = round(($pixel['green'] * (1 -$alpha) + $green * ($alpha)));
4963. $pixel['blue'] = round(($pixel['blue'] * (1 -$alpha) + $blue * ($alpha)));
4964. $color = imagecolorallocate($image_dst, $pixel['red'], $pixel['green'], $pixel['blue']);
4965. imagesetpixel($image_dst, $x, $y, $color);
4966. }
4967. }
4968. }
4969. // transforms the true color image into palette, with its merged default color
4970. if (empty($this->image_background_color)) {
4971. imagetruecolortopalette($image_dst, true, 255);
4972. $transparency = imagecolorallocate($image_dst, 254, 1, 253);
4973. imagecolortransparent($image_dst, $transparency);
4974. // make the transparent areas transparent
4975. for ($x = 0; $x < $this->image_dst_x; $x++) {
4976. for ($y = 0; $y < $this->image_dst_y; $y++) {
4977. // we test wether we have enough opacity to justify keeping the color
4978. if ($mask[$x][$y] > 120) imagesetpixel($image_dst, $x, $y, $transparency);
4979. }
4980. }
4981. }
4982. unset($mask);
4983. }
4984. break;
4985. case 'jpg':
4986. case 'bmp':
4987. // if the image doesn't support any transparency, then we merge it with the default color
4988. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;fills in transparency with default color<br />';
4989. list($red, $green, $blue) = $this->getcolors($this->image_default_color);
4990. $transparency = imagecolorallocate($image_dst, $red, $green, $blue);
4991. // make the transaparent areas transparent
4992. for ($x = 0; $x < $this->image_dst_x; $x++) {
4993. for ($y = 0; $y < $this->image_dst_y; $y++) {
4994. // we test wether we have some transparency, in which case we will merge the colors
4995. if (imageistruecolor($image_dst)) {
4996. $rgba = imagecolorat($image_dst, $x, $y);
4997. $pixel = array('red' => ($rgba >> 16) & 0xFF,
4998. 'green' => ($rgba >> 8) & 0xFF,
4999. 'blue' => $rgba & 0xFF,
5000. 'alpha' => ($rgba & 0x7F000000) >> 24);
5001. } else {
5002. $pixel = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y));
5003. }
5004. if ($pixel['alpha'] == 127) {
5005. // we have full transparency. we make the pixel transparent
5006. imagesetpixel($image_dst, $x, $y, $transparency);
5007. } else if ($pixel['alpha'] > 0) {
5008. // we have some transparency. we combine the color with the default color
5009. $alpha = ($pixel['alpha'] / 127);
5010. $pixel['red'] = round(($pixel['red'] * (1 -$alpha) + $red * ($alpha)));
5011. $pixel['green'] = round(($pixel['green'] * (1 -$alpha) + $green * ($alpha)));
5012. $pixel['blue'] = round(($pixel['blue'] * (1 -$alpha) + $blue * ($alpha)));
5013. $color = imagecolorclosest($image_dst, $pixel['red'], $pixel['green'], $pixel['blue']);
5014. imagesetpixel($image_dst, $x, $y, $color);
5015. }
5016. }
5017. }
5019. break;
5020. default:
5021. break;
5022. }
5024. // interlace options
5025. if($this->image_interlace) imageinterlace($image_dst, true);
5027. // outputs image
5028. $this->log .= '- saving image...<br />';
5029. switch($this->image_convert) {
5030. case 'jpeg':
5031. case 'jpg':
5032. if (!$return_mode) {
5033. $result = @imagejpeg($image_dst, $this->file_dst_pathname, $this->jpeg_quality);
5034. } else {
5035. ob_start();
5036. $result = @imagejpeg($image_dst, null, $this->jpeg_quality);
5037. $return_content = ob_get_contents();
5038. ob_end_clean();
5039. }
5040. if (!$result) {
5041. $this->processed = false;
5042. $this->error = $this->translate('file_create', array('JPEG'));
5043. } else {
5044. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;JPEG image created<br />';
5045. }
5046. break;
5047. case 'png':
5048. imagealphablending( $image_dst, false );
5049. imagesavealpha( $image_dst, true );
5050. if (!$return_mode) {
5051. if (is_numeric($this->png_compression) && version_compare(PHP_VERSION, '5.1.2') >= 0) {
5052. $result = @imagepng($image_dst, $this->file_dst_pathname, $this->png_compression);
5053. } else {
5054. $result = @imagepng($image_dst, $this->file_dst_pathname);
5055. }
5056. } else {
5057. ob_start();
5058. if (is_numeric($this->png_compression) && version_compare(PHP_VERSION, '5.1.2') >= 0) {
5059. $result = @imagepng($image_dst, null, $this->png_compression);
5060. } else {
5061. $result = @imagepng($image_dst);
5062. }
5063. $return_content = ob_get_contents();
5064. ob_end_clean();
5065. }
5066. if (!$result) {
5067. $this->processed = false;
5068. $this->error = $this->translate('file_create', array('PNG'));
5069. } else {
5070. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;PNG image created<br />';
5071. }
5072. break;
5073. case 'gif':
5074. if (!$return_mode) {
5075. $result = @imagegif($image_dst, $this->file_dst_pathname);
5076. } else {
5077. ob_start();
5078. $result = @imagegif($image_dst);
5079. $return_content = ob_get_contents();
5080. ob_end_clean();
5081. }
5082. if (!$result) {
5083. $this->processed = false;
5084. $this->error = $this->translate('file_create', array('GIF'));
5085. } else {
5086. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;GIF image created<br />';
5087. }
5088. break;
5089. case 'bmp':
5090. if (!$return_mode) {
5091. $result = $this->imagebmp($image_dst, $this->file_dst_pathname);
5092. } else {
5093. ob_start();
5094. $result = $this->imagebmp($image_dst);
5095. $return_content = ob_get_contents();
5096. ob_end_clean();
5097. }
5098. if (!$result) {
5099. $this->processed = false;
5100. $this->error = $this->translate('file_create', array('BMP'));
5101. } else {
5102. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;BMP image created<br />';
5103. }
5104. break;
5106. default:
5107. $this->processed = false;
5108. $this->error = $this->translate('no_conversion_type');
5109. }
5110. if ($this->processed) {
5111. if (is_resource($image_src)) imagedestroy($image_src);
5112. if (is_resource($image_dst)) imagedestroy($image_dst);
5113. $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;image objects destroyed<br />';
5114. }
5115. }
5117. } else {
5118. $this->log .= '- no image processing wanted<br />';
5120. if (!$return_mode) {
5121. // copy the file to its final destination. we don't use move_uploaded_file here
5122. // if we happen to have open_basedir restrictions, it is a temp file that we copy, not the original uploaded file
5123. if (!copy($this->file_src_pathname, $this->file_dst_pathname)) {
5124. $this->processed = false;
5125. $this->error = $this->translate('copy_failed');
5126. }
5127. } else {
5128. // returns the file, so that its content can be received by the caller
5129. $return_content = @file_get_contents($this->file_src_pathname);
5130. if ($return_content === FALSE) {
5131. $this->processed = false;
5132. $this->error = $this->translate('reading_failed');
5133. }
5134. }
5135. }
5136. }
5138. if ($this->processed) {
5139. $this->log .= '- <b>process OK</b><br />';
5140. } else {
5141. $this->log .= '- <b>error</b>: ' . $this->error . '<br />';
5142. }
5144. // we reinit all the vars
5145. $this->init();
5147. // we may return the image content
5148. if ($return_mode) return $return_content;
5150. }
5152. /**
5153. * Deletes the uploaded file from its temporary location
5154. *
5155. * When PHP uploads a file, it stores it in a temporary location.
5156. * When you {@link process} the file, you actually copy the resulting file to the given location, it doesn't alter the original file.
5157. * Once you have processed the file as many times as you wanted, you can delete the uploaded file.
5158. * If there is open_basedir restrictions, the uploaded file is in fact a temporary file
5159. *
5160. * You might want not to use this function if you work on local files, as it will delete the source file
5161. *
5162. * @access public
5163. */
5164. function clean() {
5165. $this->log .= '<b>cleanup</b><br />';
5166. $this->log .= '- delete temp file ' . $this->file_src_pathname . '<br />';
5167. @unlink($this->file_src_pathname);
5168. }
5171. /**
5172. * Opens a BMP image
5173. *
5174. * This function has been written by DHKold, and is used with permission of the author
5175. *
5176. * @access public
5177. */
5178. function imagecreatefrombmp($filename) {
5179. if (! $f1 = fopen($filename,"rb")) return false;
5181. $file = unpack("vfile_type/Vfile_size/Vreserved/Vbitmap_offset", fread($f1,14));
5182. if ($file['file_type'] != 19778) return false;
5184. $bmp = unpack('Vheader_size/Vwidth/Vheight/vplanes/vbits_per_pixel'.
5185. '/Vcompression/Vsize_bitmap/Vhoriz_resolution'.
5186. '/Vvert_resolution/Vcolors_used/Vcolors_important', fread($f1,40));
5187. $bmp['colors'] = pow(2,$bmp['bits_per_pixel']);
5188. if ($bmp['size_bitmap'] == 0) $bmp['size_bitmap'] = $file['file_size'] - $file['bitmap_offset'];
5189. $bmp['bytes_per_pixel'] = $bmp['bits_per_pixel']/8;
5190. $bmp['bytes_per_pixel2'] = ceil($bmp['bytes_per_pixel']);
5191. $bmp['decal'] = ($bmp['width']*$bmp['bytes_per_pixel']/4);
5192. $bmp['decal'] -= floor($bmp['width']*$bmp['bytes_per_pixel']/4);
5193. $bmp['decal'] = 4-(4*$bmp['decal']);
5194. if ($bmp['decal'] == 4) $bmp['decal'] = 0;
5196. $palette = array();
5197. if ($bmp['colors'] < 16777216) {
5198. $palette = unpack('V'.$bmp['colors'], fread($f1,$bmp['colors']*4));
5199. }
5201. $im = fread($f1,$bmp['size_bitmap']);
5202. $vide = chr(0);
5204. $res = imagecreatetruecolor($bmp['width'],$bmp['height']);
5205. $P = 0;
5206. $Y = $bmp['height']-1;
5207. while ($Y >= 0) {
5208. $X=0;
5209. while ($X < $bmp['width']) {
5210. if ($bmp['bits_per_pixel'] == 24)
5211. $color = unpack("V",substr($im,$P,3).$vide);
5212. elseif ($bmp['bits_per_pixel'] == 16) {
5213. $color = unpack("n",substr($im,$P,2));
5214. $color[1] = $palette[$color[1]+1];
5215. } elseif ($bmp['bits_per_pixel'] == 8) {
5216. $color = unpack("n",$vide.substr($im,$P,1));
5217. $color[1] = $palette[$color[1]+1];
5218. } elseif ($bmp['bits_per_pixel'] == 4) {
5219. $color = unpack("n",$vide.substr($im,floor($P),1));
5220. if (($P*2)%2 == 0) $color[1] = ($color[1] >> 4) ; else $color[1] = ($color[1] & 0x0F);
5221. $color[1] = $palette[$color[1]+1];
5222. } elseif ($bmp['bits_per_pixel'] == 1) {
5223. $color = unpack("n",$vide.substr($im,floor($P),1));
5224. if (($P*8)%8 == 0) $color[1] = $color[1] >>7;
5225. elseif (($P*8)%8 == 1) $color[1] = ($color[1] & 0x40)>>6;
5226. elseif (($P*8)%8 == 2) $color[1] = ($color[1] & 0x20)>>5;
5227. elseif (($P*8)%8 == 3) $color[1] = ($color[1] & 0x10)>>4;
5228. elseif (($P*8)%8 == 4) $color[1] = ($color[1] & 0x8)>>3;
5229. elseif (($P*8)%8 == 5) $color[1] = ($color[1] & 0x4)>>2;
5230. elseif (($P*8)%8 == 6) $color[1] = ($color[1] & 0x2)>>1;
5231. elseif (($P*8)%8 == 7) $color[1] = ($color[1] & 0x1);
5232. $color[1] = $palette[$color[1]+1];
5233. } else
5234. return FALSE;
5235. imagesetpixel($res,$X,$Y,$color[1]);
5236. $X++;
5237. $P += $bmp['bytes_per_pixel'];
5238. }
5239. $Y--;
5240. $P+=$bmp['decal'];
5241. }
5242. fclose($f1);
5243. return $res;
5244. }
5246. /**
5247. * Saves a BMP image
5248. *
5249. * This function has been published on the PHP website, and can be used freely
5250. *
5251. * @access public
5252. */
5253. function imagebmp(&$im, $filename = "") {
5255. if (!$im) return false;
5256. $w = imagesx($im);
5257. $h = imagesy($im);
5258. $result = '';
5260. // if the image is not true color, we convert it first
5261. if (!imageistruecolor($im)) {
5262. $tmp = imagecreatetruecolor($w, $h);
5263. imagecopy($tmp, $im, 0, 0, 0, 0, $w, $h);
5264. imagedestroy($im);
5265. $im = & $tmp;
5266. }
5268. $biBPLine = $w * 3;
5269. $biStride = ($biBPLine + 3) & ~3;
5270. $biSizeImage = $biStride * $h;
5271. $bfOffBits = 54;
5272. $bfSize = $bfOffBits + $biSizeImage;
5274. $result .= substr('BM', 0, 2);
5275. $result .= pack ('VvvV', $bfSize, 0, 0, $bfOffBits);
5276. $result .= pack ('VVVvvVVVVVV', 40, $w, $h, 1, 24, 0, $biSizeImage, 0, 0, 0, 0);
5278. $numpad = $biStride - $biBPLine;
5279. for ($y = $h - 1; $y >= 0; --$y) {
5280. for ($x = 0; $x < $w; ++$x) {
5281. $col = imagecolorat ($im, $x, $y);
5282. $result .= substr(pack ('V', $col), 0, 3);
5283. }
5284. for ($i = 0; $i < $numpad; ++$i)
5285. $result .= pack ('C', 0);
5286. }
5288. if($filename==""){
5289. echo $result;
5290. } else {
5291. $file = fopen($filename, "wb");
5292. fwrite($file, $result);
5293. fclose($file);
5294. }
5295. return true;
5296. }
5297. }
5299. ?>