-1

NOTE: it seems some think I am asking the question "Should I use this code style?", but I am actually asking "How can I achieve this?". Sorry If my question is confusing.

To create an image with PHP you can use these kind of base functions:

http://php.net/manual/en/ref.image.php

But by default it seems rather static. Example:

/* file: PHPImage.php */

$img = imagecreatefrompng('logo.png');

// Do some stuff to that image

header('Content-type: image/png');
imagepng($img);
imagedestroy($img);

I would like to create a class that can manipulate images on the fly and pass it a function that can manipulate the $img on a call back, and do all of that inline.. something like this:

<?php
    $img = new PHPImage("baseimage.png", function(&$thisimg){
        // Color functions here etc
    });
?>

<img src="<?php echo $img->URLResource; ?>" />

I see that this is a feeble example but just wondering if this kind of workflow is possible.

What I'm wondering is: I get that you could pass GET parameters to a constant page setup for this eg. scripts/PHPImage.php?w=160&h=160&bgcol=255-0-0, and then use the passed parameters to run the actual image functions on that page. But is there anyway you could use the actual functions on the image and generate it in a casual workflow, like my PHPImage class example above?

Thanks in advance for any help!

Zephni
  • 753
  • 1
  • 7
  • 26
  • 1
    This is to broad for stack overflow, `like my PHPImage class example above` yes make a "wrapper" or "decorator" class. I have a very old one I wrote some years ago not sure how much of it still works. Your welcome to use it as a starting place [GitHub](https://github.com/ArtisticPhoenix/MISC/tree/master/Image). I wrote it for a specific site back in probably 2010, so somethings are only partial implemented, I never got around to finishing it up... :-/ – ArtisticPhoenix Oct 23 '18 at 16:42
  • [so] is not for general design discussions. You have to ask a specific question about code you've written, not advice about code you're considering. – Barmar Oct 23 '18 at 16:44
  • You can have your custom class use any signature you want, such as passing $_GET as additional parameter and treat w/h as options. So the answer to your question would be yes. – mario Oct 23 '18 at 16:47
  • Try use [intervention](http://image.intervention.io/) – ventaquil Oct 23 '18 at 16:48
  • @ArtisticPhoenix I see what you are both saying yet, my question isn't so much "should I do this" but "how" can I do this, I was just using an example of the top most code, but not 100% sure how to implement it. – Zephni Oct 26 '18 at 08:30
  • The call back would work fine, the only issue you will have is scoping it inside of the class, because you define it outside you wont have access to `$this` meaning the class you send the callback to (but there is a way around that). http://php.net/manual/en/closure.bindto.php Then you wouldn't need to pass anything in. – ArtisticPhoenix Oct 26 '18 at 09:05
  • @ArtisticPhoenix my plan was to use a "&" as a pointer to the image that is created in the construct for PHPImage. So that part isn't so much a problem as what I would reference to in the $URLResource when outputting the image to the same page. Sorry I realize I am bad at asking questions :( – Zephni Oct 26 '18 at 09:44
  • 1
    `&` should work by reference, but I never tried it with a resource. I imagine it works though, I have yet another class on github that is an ajax wrapper same kind of idea [HERE](https://github.com/ArtisticPhoenix/MISC/tree/master/AjaxWrapper) it traps output and exceptions thrown when returning AJAX, something that's incredibly useful. – ArtisticPhoenix Oct 26 '18 at 10:02
  • I will check all your stuff out sounds interesting, you're a busy bee! – Zephni Oct 26 '18 at 10:04

1 Answers1

1

For an example

<?php
echo "<pre>";

class PHPImage{
    protected $callback;
    protected $src = '';
    protected $image = null;
    protected $type = null;

    public function __construct($src, $callback=null){
        $this->src = $src;
        $this->type = exif_imagetype($this->src);
        $this->image = $this->open($this->src);

        $this->callback = $callback->bindTo($this); 
        //bingTo, changes scope to this class
        //that lets us access internal methods
        //for exmaple if we had a method PHPImage::hight($image);
        //we could access it using $this->height($image); from inside
        //the callback  function($image){ $height = $this->height($image); }
    }

    public function execute(){
        if(!$this->callback)return false;
        $this->image = $this->callback->__invoke($this->image); //call the magic method __invoke ($this->callback(), is not a method)
        return $this; //for  method chaining  $obj->foo()->bar();
    }

    public function open($src){
        //if called directly
        $type = $this->type ? $this->type : exif_imagetype($src);
        switch($type)
        {
            case IMAGETYPE_GIF:
                return imagecreatefromgif($src);
                break;
            case IMAGETYPE_JPEG:
                return imagecreatefromjpeg($src);
                break;
            case IMAGETYPE_PNG:
                $image = imagecreatefrompng($src);
                imagealphablending($image, true); // setting alpha blending on
                imagesavealpha($image, true); // save alphablending setting (important)
                return $image;
                break;
            case IMAGETYPE_WBMP:
                return imagecreatefromwbmp($src);
                break;
            default:
                throw new Exception('Unknown image type', 1);
        }
    }

    public function save($dest, $res=90){
        switch($this->type){
            case IMAGETYPE_GIF:
                imagegif($this->image, $dest, $res);
                break;
            case IMAGETYPE_JPEG:
                imagejpeg($this->image, $dest, $res);
                break;
            case IMAGETYPE_PNG:
                $res = ceil($res*0.1); //convert from 0-100 to 1-10
                imagepng($this->image, $dest, $res);
                break;
            case IMAGETYPE_WBMP:
                imagewbmp($this->image, $dest, $res);
                break;
            default:
                throw new Exception('Unknown image type',1);
        }
    }

}


(new PHPImage('C:\UniServerZ\www\artisticphoenix\public_html\wp\wp-content\uploads\2018\10\ajax.png', function($image){
    return imagerotate($image, 90, 0);
}))->execute()->save(__DIR__.'/new.png');

echo "Complete";

I tested this (and it works, mostly, some issues with transparent PNGs) most of the code was taken (and modified) from my image class I mentioned that's on GitHub

Basically any GD functions that accept an image resource from on of the functions in PHPImage::open() would work by feeding it the $image argument inside the callback.

I should note the $image is a resource and not an object, so you have to pass it back with return, you may be able to do it like function(&$image) but I didn't test that.

Enjoy!

ArtisticPhoenix
  • 21,464
  • 2
  • 24
  • 38
  • Wow I didn't expect a whole class! Thanks, that all makes sense, so one final question: Do I HAVE to save the image before outputting it in a , I guess I was wondering if I could pass the image data to a php page that is of an image mime type, then use that as the img src. I am happy to tick your answer, just want to check this final point which I poorly worded in my original question! – Zephni Oct 26 '18 at 09:50
  • 1
    No, you do not have to save it, you can return it as a `base64_encoded()` string, and there is some special stuff to put in `src`... yada yada, you can google and find that easy enough. (something I didn't know when I wrote the original class) Here is a SO post on that https://stackoverflow.com/questions/8499633/how-to-display-base64-images-in-html – ArtisticPhoenix Oct 26 '18 at 09:52
  • Ok thanks, I guess I didn't really know what to search for but that makes sense. Cheers for all your help! – Zephni Oct 26 '18 at 09:53
  • 1
    I guess you can capture the output with `ob_` output buffering, this other post shows how https://stackoverflow.com/questions/1206884/php-gd-how-to-get-imagedata-as-binary-string In my original class is a method named `render` but I never got it to work ... lol (I wrote that about 6 years ago) – ArtisticPhoenix Oct 26 '18 at 09:54
  • I been working on a similar callback for my shutdown/error handler class, basically the idea is to pass it a writer (predefined) or send it a callback, to log, show, email errors. Its [HERE](https://github.com/ArtisticPhoenix/Shutdown) but that (and other things) is how I know how to do the `bindTo` and callback stuff like `__invoke` cheers. – ArtisticPhoenix Oct 26 '18 at 09:59
  • Well time for bed, I just setup a SASS compiler for my wordpress site (Yea me!). One last thing you might find interesting I once built a mail order bride site that stored a users images in a zip, and then I had a PHP file that streamed them from the zip (no file creation) that worked great as we had to restrict access to the images from off site viewers. And there was like 60 gigs of images all total, the orignal site was built in 99, I redid it in 2010, and they had stored all the images as blobs in the DB, it was a nightmare... lol – ArtisticPhoenix Oct 26 '18 at 10:04