note 117021 deleted from ref.image by cmb
| From: | cmb@php.net | Date: | Thu, 13 Oct 2016 17:33:49 +0000 |
| Subject: | note 117021 deleted from ref.image by cmb | ||
| References: | 1 | Groups: | php.notes |
| Request: | Send a blank email to php-notes+get-206884@lists.php.net to get a copy of this message | ||
Note Submitter: str_replace('o', 'x', 'nitrogen');
----
I was after a technique to produce an image by using the image resources available to PHP and to
have access to the image's binary data directly in PHP WITHOUT saving to a temporary file.
My purpose of this was to produce a directory of images with small image thumbnails (16x16) next to
the filenames. Instead of having countless tiny images saved, I wanted to print out the image data
into the <img> HTML tag (inline) using the data URI scheme.
I found no such code or suggestion for this, and I've done some digging around at likely
approaches and finally came up with a solution. There may or may not be a better way of doing this,
but this way works for me.
The guts of the approach started here with the example of registering a class as a stream wrapper:
http://php.net/manual/en/stream.streamwrapper.example-1.php
- this way we have access to, and can over-ride, the behaviour of "file" I/O with a custom
wrapper.
<?php
// first, we define our class for the stream wrapper
class VariableStream {
var $position;
var $varname;
function stream_open($path, $mode, $options, &$opened_path) {
$url = parse_url($path);
$this->varname = $url['host'];
$this->position = 0;
return TRUE;
}
function stream_write($data) {
$left = substr(@$GLOBALS[$this->varname], 0, $this->position);
$right = substr(@$GLOBALS[$this->varname], $this->position+strlen($data));
$GLOBALS[$this->varname] = $left.$data.$right;
$this->position+= strlen($data);
return strlen($data);
}
function stream_eof() {
return $this->position>=strlen($GLOBALS[$this->varname]);
}
}
// register the class as a stream wrapper ("var://asdf")
stream_wrapper_register('var', 'VariableStream');
// create a really simple dynamically-generated image
// in my case, I used imagecreatefromjpeg to create 16x16 thumbnails
$im = imagecreatetruecolor(130, 36);
imagefill($im, 0, 0, 0xAAAAAA);
imagestring($im, 5, 10, 10, 'Hello world!', 0x0000FF);
// and output it to our wrapper!
imagepng($im, 'var://asdf/'); // $asdf now contains our image binary!
imagedestroy($im); // free memory
$asdf = base64_encode($asdf); // base64 encode our data for...
printf("<img alt=\"\" src=\"data:image/png;base64,%s\"/>",
$asdf);
?>
The class 'VariableStream' lacks ability to seek, ftell, and read for the sake of simple
code for my purpose. More complete code for I/O operations can be found in the example document I
references above. You could also then use fopen using the wrapper and variable name to access it
like a file again.
This technique can be applied to other functions that don't allow direct access to the data
generated to files or sockets.
Hope this helps!