Documentation is available at ASCIIArtist.php
1 <?php
2 /**
3 * ASCIIArtist - Class to convert Bitmap-Images into nice ASCII Texts in HTML format
4 *
5 * Copyright (c) 2004, Sebastian Röbke <sebastian@sebastian-r.de>
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * - Redistributions of source code must retain the above copyright notice, this
12 * list of conditions and the following disclaimer.
13 * - Redistributions in binary form must reproduce the above copyright notice,
14 * this list of conditions and the following disclaimer in the documentation
15 * and/or other materials provided with the distribution.
16 * - Neither the name of Sebastian Röbke nor the names of its contributors may be
17 * used to endorse or promote products derived from this software without
18 * specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
26 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
29 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 *
31 * Credits: Florian Schäfer, Maxi Kellner, Andrea Spacca, Alastair Battrick
32 * Requirements: PHP >= 4.3.x with GD support for the desired image format
33 *
34 * @author Sebastian Röbke <asciiartist@sebastian-r.de>
35 * @version 1.4
36 * @link http://www.sebastian-r.de/asciiart/
37 * @package ASCIIArtist
38 * @license BSD
39 */
40
41 /**
42 * ASCIIArtist class
43 *
44 * @package ASCIIArtist
45 */
46 class ASCIIArtist
47 {
48 /**
49 * The current class version
50 *
51 * @var string
52 * @access private
53 * @see getVersion()
54 */
55 var $_version = "1.4";
56
57 /**
58 * Array for error messages
59 *
60 * @var array
61 * @access private
62 * @see isError(), getErrors()
63 */
64 var $_errors = array();
65
66 /**
67 * The replace characters from dark to light used by render modes 0 and 1
68 * (current version can handle 9 variations)
69 *
70 * @var array
71 * @access private
72 */
73 var $_replaceCharacters = array (
74 1 => "W",
75 2 => "@",
76 3 => "#",
77 4 => "*",
78 5 => "+",
79 6 => ":",
80 7 => ".",
81 8 => ",",
82 9 => " "
83 );
84
85 /**
86 * Possible image types
87 *
88 * @var array
89 * @access private
90 */
91 var $_imageTypes = array (
92 1 => "gif",
93 2 => "jpeg",
94 3 => "png"
95 );
96
97 /**
98 * Image resource
99 *
100 * @var resource
101 * @access private
102 */
103 var $_image = 0;
104
105 /**
106 * Image file height
107 *
108 * @var integer
109 * @access private
110 */
111 var $_imageHeight = 0;
112
113 /**
114 * Image file height
115 *
116 * @var integer
117 * @access private
118 */
119 var $_imageWidth = 0;
120
121 /**
122 * Container for the rendered HTML/ASCII image
123 *
124 * @var string
125 * @access private
126 * @see getHTMLImage()
127 */
128 var $_imageHTML = '';
129
130 /**
131 * CSS for the HTML Image Output
132 *
133 * @var string
134 * @access private
135 * @see setImageCSS()
136 */
137 var $_imageCSS = '
138 color : #000000;
139 background-color : #FFFFFF;
140 font-size : 8px;
141 font-family : "Courier New", Courier, mono;
142 line-height : 5px;
143 letter-spacing : -1px;
144 ';
145
146 /**
147 * CSS for the Error Output
148 *
149 * @var string
150 * @access private
151 * @see setErrorCSS()
152 */
153 var $_errorCSS = '
154 text-align : center;
155 color : #000000;
156 background-color : #EFEFEF;
157 font-size : 11px;
158 font-family : Verdana, Arial, sans-serif;
159 border-color : #333333;
160 border-style : solid;
161 border-width : 1px;
162 margin : 4px;
163 padding : 4px;
164 ';
165
166 /**
167 * Var to remember the last font tag
168 *
169 * @var array
170 * @access private
171 */
172 var $_lastRGB = array();
173
174 /**
175 * Var to remember the font tag state
176 *
177 * @var boolean
178 * @access private
179 */
180 var $_fontTagOpen = false;
181
182 /**
183 * Returns the hex string of a rgb array
184 *
185 * Example:
186 * $rbg = array("red" -> 255, "green" -> 255, "blue" -> 255);
187 * rgb2hex($rgb) will return "FFFFFF"
188 *
189 * @param array $rgb An array of red, green and blue values
190 * @return string The hex values as one string
191 * @access private
192 */
193 function _RGB2HEX($rgb)
194 {
195 return sprintf("%02X%02X%02X",$rgb["red"],$rgb["green"],$rgb["blue"]);
196 }
197
198 /**
199 * Renders the given pixel
200 *
201 * @param integer $mode Current version can handle mode 1, 2 or 3
202 * @param integer $x X Position of the image
203 * @param integer $y Y Position of the image
204 * @param string $fixedChar Needed for mode 3
205 * @access private
206 */
207 function _renderPixel($mode, $x, $y, $fixedChar)
208 {
209 // RGB Value of current pixel (Array)
210 $rgb = imagecolorsforindex($this->_image, imagecolorat($this->_image, $x, $y));
211
212 // Replace by mode
213 switch ($mode) {
214 case 1:
215 // Rounded Brightness
216 $brightness = $rgb["red"] + $rgb["green"] + $rgb["blue"];
217
218 // Choose replacing character
219 $replaceCharacterNo = round($brightness / 100) + 1;
220
221 $this->_imageHTML .= $this->_replaceCharacters[$replaceCharacterNo];
222 break;
223 case 2:
224 // Rounded Brightness
225 $brightness = $rgb["red"] + $rgb["green"] + $rgb["blue"];
226
227 // Choose replacing character
228 $replaceCharacterNo = round($brightness / 100) + 1;
229
230 if ($this->_lastRGB == $rgb) {
231 $this->_imageHTML .= $this->_replaceCharacters[$replaceCharacterNo];
232 } else {
233
234 if ($this->_fontTagOpen) {
235 $this->_imageHTML .= "</font>";
236 }
237
238 $this->_imageHTML .= "<font color=\"#".$this->_RGB2HEX($rgb)."\">".$this->_replaceCharacters[$replaceCharacterNo];
239 $this->_fontTagOpen = true;
240 }
241 break;
242 case 3:
243 if ($this->_lastRGB == $rgb) {
244 $this->_imageHTML .= $fixedChar;
245 } else {
246
247 if ($this->_fontTagOpen) {
248 $this->_imageHTML .= "</font>";
249 }
250
251 $this->_imageHTML .= "<font color=\"#".$this->_RGB2HEX($rgb)."\">".$fixedChar;
252 $this->_fontTagOpen = true;
253 }
254 break;
255
256 }
257
258 $this->_lastRGB = $rgb;
259 }
260
261 /**
262 * Returns the class version number
263 *
264 * @return string The class version number
265 * @access public
266 */
267 function getVersion ()
268 {
269 return $this->_version;
270 }
271
272 /**
273 * Formatting the HTML Image using CSS
274 *
275 * Tip: Use width-fixed fonts such as Courier only.
276 *
277 * @param string $css Stylesheet for the image
278 * @access public
279 */
280 function setImageCSS ($css)
281 {
282 $this->_imageCSS = $css;
283 }
284
285 /**
286 * Formatting error messages using CSS
287 *
288 * @param string $css Stylesheet for error message
289 * @access public
290 */
291 function setErrorCSS ($css)
292 {
293 $this->_errorCSS = $css;
294 }
295
296 /**
297 * Renders the image into HTML
298 *
299 * The following modes are implemented:
300 * 1 = black/white using $replaceCharacters by brightness,
301 * 2 = colourized using $replaceCharacters by brightness,
302 * 3 = colourized using a fixed character definded by $fixedChar.
303 * A resolution of 1 means that every pixel is being replaced,
304 * whereas 5 for example means a scanned block of 5 pixel height and width,
305 * resulting in less data to replace.
306 *
307 * @param integer $mode Current version can handle mode 1, 2 or 3
308 * @param integer $resolution Resolution for scanning the bitmap.
309 * @param string $fixedChar Needed for mode 3
310 * @param boolean $flipH Flip output horizontally?
311 * @param boolean $flipV Flip output vertically?
312 * @access public
313 * @see getHTMLImage()
314 */
315 function renderHTMLImage($mode = 1, $resolution = 2, $fixedChar = 'W', $flipH = false, $flipV = false)
316 {
317 $this->_imageHTML = '';
318
319 // Minimum value for $resolution is 1
320 if ($resolution < 1) {
321 $resolution = 1;
322 }
323
324 // Different loops for flipping
325 if (!$flipH && !$flipV) {
326 // Y-Axis
327 for ($y = 0; $y < $this->_imageHeight; $y += $resolution)
328 {
329 // X-Axis
330 for ($x = 0; $x < $this->_imageWidth; $x += $resolution)
331 {
332 $this->_renderPixel($mode, $x, $y, $fixedChar);
333 }
334 $this->_imageHTML .= "<br>\n";
335 }
336 }
337 else if ($flipH && !$flipV) {
338 // Y-Axis
339 for ($y = 0; $y < $this->_imageHeight; $y += $resolution)
340 {
341 // X-Axis
342 for ($x = $this->_imageWidth; $x > 0; $x -= $resolution)
343 {
344 $this->_renderPixel($mode, $x, $y, $fixedChar);
345 }
346 $this->_imageHTML .= "<br>\n";
347 }
348 }
349 else if (!$flipH && $flipV) {
350 // Y-Axis
351 for ($y = $this->_imageHeight; $y > 0; $y -= $resolution)
352 {
353 // X-Axis
354 for ($x = 0; $x < $this->_imageWidth; $x += $resolution)
355 {
356 $this->_renderPixel($mode, $x, $y, $fixedChar);
357 }
358 $this->_imageHTML .= "<br>\n";
359 }
360 }
361 else if ($flipH && $flipV) {
362 // Y-Axis
363 for ($y = $this->_imageHeight; $y > 0; $y -= $resolution)
364 {
365 // X-Axis
366 for ($x = $this->_imageWidth; $x > 0; $x -= $resolution)
367 {
368 $this->_renderPixel($mode, $x, $y, $fixedChar);
369 }
370 $this->_imageHTML .= "<br>\n";
371 }
372 }
373 if ($this->_fontTagOpen) {
374 $this->_imageHTML .= "</font>\n";
375 }
376 }
377
378 /**
379 * Returns the rendered ASCII HTML image and CSS
380 *
381 * @return string The rendered HTML image and CSS
382 * @access public
383 */
384 function getHTMLImage()
385 {
386 return '<style type="text/css">'
387 .'.asciiimage{'
388 .$this->
389 _imageCSS .'}</style>'
390 .'<span class="asciiimage">'
391 .$this->
392 _imageHTML .'</span>';
393 }
394
395 /**
396 * Checks if an error has occured
397 *
398 * @return boolean
399 * @access public
400 * @see getErrors(), getHTMLErrors()
401 */
402 function isError()
403 {
404 return count($this->_errors) > 0;
405 }
406
407
408 /**
409 * Returns the unformatted error messages as an array
410 *
411 * @return array The error messages
412 * @access public
413 * @see isError()
414 */
415 function getErrors()
416 {
417 return $this->_errors;
418 }
419
420 /**
421 * Returns the error messages as HTML
422 *
423 * @return string The error messages as HTML
424 * @access public
425 * @see setErrorCSS()
426 */
427 function getHTMLErrors()
428 {
429 if (!$this->isError()) {
430 return '';
431 }
432
433 $ret = '<style type="text/css">'
434 .'.asciierror{'
435 .$this->
436 _errorCSS .'}</style>'
437 .'<div class="asciierror">';
438
439 foreach($this->_errors as $error) {
440 $ret.= '<b>Error:</b> '.htmlentities($error).'<br>';
441 }
442
443 $ret.= '</div>';
444
445 return $ret;
446 }
447
448 /**
449 * Tries to set the given bitmap image as source for the ASCII image
450 * and determines width and height
451 *
452 * If $filename begins with "http://" (not case sensitive), an HTTP 1.0 connection
453 * is opened to the specified server, the page is requested using the HTTP GET method.
454 * If filename begins with "ftp://" (not case sensitive), an ftp connection to the
455 * specified server is opened.
456 * If the server does not support passive mode ftp, this will fail.
457 * If filename is one of "php://stdin", "php://stdout", or "php://stderr",
458 * the corresponding stdio stream will be opened.
459 * If filename begins with anything else, the file will be opened from the filesystem.
460 *
461 * @param string $filename
462 * @return boolean
463 * @access public
464 */
465 function setFile($filename)
466 {
467 if (!$imagesize = getimagesize($filename)) {
468 $this->_errors[] = 'Cannot open "'.$filename.'" for reading.';
469 return false;
470 }
471
472 // Create Image from file by type, get and set size
473 list($width,$height,$type) = $imagesize;
474 switch ($type) {
475 case 1:
476 case 2:
477 case 3:
478 $imagefunction = "imagecreatefrom".$this->_imageTypes[$type];
479
480 if (!function_exists($imagefunction) || !$this->_image = $imagefunction($filename)) {
481 $this->_errors[] = 'Unable to create images from '.$this->_imageTypes[$type].'. See http://de.php.net/manual/en/ref.image.php for more info.';
482 return false;
483 }
484
485 $this->_imageHeight = $height;
486 $this->_imageWidth = $width;
487
488 break;
489 default:
490 $this->_errors[] = 'Cannot determine image type of "'.$filename.'".';
491 return false;
492 }
493
494 return true;
495 }
496
497 /**
498 * Returns the height of the original bitmap image in pixels
499 *
500 * @return integer
501 * @access public
502 */
503 function getImageHeight()
504 {
505 return $this->_imageHeight;
506 }
507
508 /**
509 * Returns the width of the original bitmap image in pixels
510 *
511 * @return integer
512 * @access public
513 */
514 function getImageWidth()
515 {
516 return $this->_imageWidth;
517 }
518 }
519 ?>
Documentation generated on Sun, 4 Jan 2004 14:03:04 +0100 by phpDocumentor 1.2.3