php get parameter reset with headers - php

I have the following scenario. I have about around 600 pictures. Most of theme have in bottom a logo which should be cut it out because branding issue, but not all of theme.(with ftp and photoshop would be a challange)The approach what I was thinking about I list all of my images form folders and I add to theme a hyperlink which should fire on a method class which cuts out 57px from bottom, because the image listing limited to height and width, after cutting should not be present on the page
the url looks like
cut.php?target=http://example.com/hideit/2012/03/myimage.jpg
I want to reset the get parameter after execution to avoid problems on page refresh while would cut again from that image the defined pixels. I was trying the following
function cutAndsave($jpg){
$folder = explode('/', $jpg);
$path = 'I:\\xampp\\htdocs\\hideit\\'. $folder[4]. '\\'. $folder[5] .'\\'.$folder[6] ;
list($width, $height) = getimagesize($jpg);
$offset_x = 0;
$offset_y = 0;
$new_height = $height - 57;
$new_width = $width;
$image = imagecreatefromjpeg($jpg);
$new_image = imagecreatetruecolor($new_width, $new_height);
imagecopy($new_image, $image, 0, 0, $offset_x, $offset_y, $width, $height);
header('Content-Type: image/jpeg');
imagejpeg($new_image,$path, 90);
header("Location: /cat.php/");
die();
}
but the last header call won't work in my case

Your concrete problem at hand is that you're trying to send an HTTP header after you output an image. HTTP headers can only be sent before any content; they're headers after all.
The bigger problem is that the idea is nonsense.
The client requests a URL, example.com/image.php?id=42.jpg. You may think of this URL as a filename. The image is identified by the filename/URL. Different URL, different image. It also doesn't matter that this is a PHP script and not a physical file on a hard disk somewhere, that detail is irrelevant to the client. The client requests the URL and receives an image in return, that's all that matters. Whether the image is just read as is from a data storage, is resized by a script on the fly, is live drawn by unicorns behind the scenes, that all doesn't matter; it's an implementation detail.
URL request, response. That's the important concept you need to grok for working with web servers.
As such, "resetting URL parameters" is pointless. You can't do that. You can redirect the client to a different URL, but that's a different file/URL then. If you want the client to get the image, you respond with an image whenever the client asks for the URL. If the user refreshes the page so the client requests the URL again, so be it.
If you do not want to do the image cutting again and again, cache the resized file. In code, check:
Oh, somebody's requesting image #42.
Do I have a resized version of image #42 already?
If no, create a resized version and save it somewhere.
Serve the resized image #42.
On top of that you can set HTTP headers that influence the client's caching behavior, so the client will keep the image in its cache and not request it again every time.
In case it's also as simple as not overwriting the original. Always keep the original intact, the cut version should be a copy of it. You can either generate that copy as described above, or when the original is uploaded. But don't change the behavior of a URL depending on whether you have already processed the image or not.

You have an error in line header("Location: /cat.php/");
It should be
header("Location: /cut.php");
if you just want to go back to last page.
If you want to additionally show your image you can do
header("Location: /cut.php?show=$path")
and then do a script in your file which prints an <img> tag.

Related

PHP Multiple Image Scripts On One Image Source

I have 2 different scripts for handling images:
The first one is a watermark script for watermarking images on the fly:
$imgpath=$_REQUEST['filename'];
header('content-type: image/jpeg');
$watermarkfile="assets/img/logo_variations/logo_watermark_75.png";
$watermark = imagecreatefrompng($watermarkfile);
list($watermark_width,$watermark_height) = getimagesize($watermarkfile);
$image = imagecreatefromjpeg($imgpath);
$size = getimagesize($imgpath);
$dest_x = ($size[0] - $watermark_width)/2;
$dest_y = ($size[1] - $watermark_height)/2;
imagecopy($image, $watermark, $dest_x, $dest_y, 0, 0, $watermark_width, $watermark_height);
imagejpeg($image);
imagedestroy($image);
imagedestroy($watermark);
So the image URL for a watermarked image is: http://example.com/watermark.php?filename=assets/img/temp/temp_share.jpg or since I'm using mod_rewrite to "pretty up" my URL: http://example.com/watermark/assets/img/temp/temp_share.jpg.
Works like a charm and my reason for doing so like this is because this is on a modeling website where I want to display the images without watermarks but I use a jquery script to change the image source of the image gets right clicked(assuming a user is trying to save the image).
The script only changes the source of any image with a class of img-protected.
I've written it to ignore any image with watermark in the URL so that it doesn't try to change the already watermarked image which would result in a url like: http://example.com/watermark/watermark/img.jpg which would result in a broken image. The other part is written to remove http://example.com from the original source so I don't end up with http://example.com/watermark/http://example.com/img.jpg.
$('.img-protected').on('mousedown', function (event) {
if (event.which == 3) {
if(this.src.indexOf("watermark") > -1) {
return false;
}
else {
src = this.src.replace('http://example.com/','');
this.src = 'http://example.com/watermark/' + src;
}
}
});
All of this works exceptionally well until I added another image handling script:
I'm using TimThumb.php which is an on the fly image resize script I use for creating gallery icons instead of uploading an icon and a full size image(this is how I wish to keep doing so as well).
The problem I am facing is this:
If I have an image that is being turned into a thumbnail using TimThumb.php which I renamed to thumb.php on my server the URL is http://example.com/thumb.php?src=gallery/goth/industrial_brick/5361ae7de9404.jpg&w=350&h=500a=c&s=1&f=11 which gives me an icon for 5361ae7de9404.jpg.
All of my icons have a class of img-protected which means on right click the above URL is going to be changed to the watermarked one.
This is where it fails.
The outputed URL when right clicked is http://example.com/watermark/http://www.example.com/thumb.php?src=gallery/goth/industrial_brick/5361ae7de9404.jpg&w=350&h=500a=c&s=1&f=11 which results in a broken image.
I manually tried making the URL into http://example.com/watermark/thumb.php?src=gallery/goth/industrial_brick/5361ae7de9404.jpg&w=350&h=500a=c&s=1&f=11 to see if that would change anything but it still results in a broken image.
What I need is to be able to also watermark the generated icons from thumb.php using watermark.php.
Is there a way to combine these two scripts or a workaround to make this work?
I'm at a complete loss here.
EDIT: I am fully aware that advanced users can still acquire the non watermarked image since it's already been downloaded to there device, but I don't expect a high volume of users to visit this particular website as this is simply a local models portfolio.

Right way of watermarking & storing & displaying images in PHP

I'm building a web based system, which will host loads and loads of highres images, and they will be available for sale. Of course I will never display the highres image, instead when browsing people will only see a low resolution, watermarked image. Currently the workflow is as follows:
PHP script handles the highres image upload, when image is uploaded, it's automatically re-sized to a low res image and to a thumbnail image as well and both of the files are saved on the server, (no watermark is added).
When people are browsing, the page displays the thumbnail of the image, on click, it enlarges and displays the lowres image with watermark as well. At the time being I apply the watermark on the fly whenever the lowres image is opened.
My question is, what is the correct way:
1) Should I save a 2nd copy of the lowres image with thumbnail, only when it's access for the first time? I mean if somebody access the image, I add the watermark on the fly, then display the image & store it on the server. Next time the same image is accessed if a watermarked copy exist just display the wm copy, otherwise apply watermark on the fly. (in case watermark.png is changed, just delete the watermarked images and they will be recreated as accessed).
2) Should I keep applying watermarks on the fly like I'm doing now.
My biggest question is how big is the difference between a PHP file_exists(), and adding a watermark to an image, something like:
$image = new Imagick();
$image->readImage($workfolder.$event . DIRECTORY_SEPARATOR . $cat . DIRECTORY_SEPARATOR .$mit);
$watermark = new Imagick();
$watermark->readImage($workfolder.$event . DIRECTORY_SEPARATOR . "hires" . DIRECTORY_SEPARATOR ."WATERMARK.PNG");
$image->compositeImage($watermark, imagick::COMPOSITE_OVER, 0, 0);
All lowres images are 1024x1024, JPG with a quality setting of 45%, and all unnecessary filters removed, so the file size of a lowres image is about 40Kb-80Kb.
It is somehow related to this question, just the scale and the scenarios is a bit different.
I'm on a dedicated server (Xeon E3-1245v2) cpu, 32 GB ram, 2 TB storage), the site does not have a big traffic overall, but it has HUGE spikes from time to time. When images are released we get a few thousand hits per hours with people browsing trough the images, downloading, purchasing, etc. So while on normal usage I'm sure that generating on the fly is the right approach, I'm a bit worried about the spike period.
Need to mention that I'm using ImageMagick library for image processing, not GD.
Thanks for your input.
UPDATE
None of the answers where a full complete solution, but that is good since I never looked for that. It was a hard decision which one to accept and whom to accord the bounty.
#Ambroise-Maupate solution is good, but yet it's relay on the PHP to do the job.
#Hugo Delsing propose to use the web server for serving cached files, lowering the calls to PHP script, which will mean less resources used, on the other hand it's not really storage friendly.
I will use a mixed-merge solution of the 2 answers, relaying on a CRON job to remove the garbage.
Thanks for the directions.
Personally I would create a static/cookieless subdomain in a CDN kinda way to handle these kind of images. The main reasons are:
Images are only created once
Only accessed images are created
Once created, an image is served from cache and is a lot faster.
The first step would be to create a website on a subdomain that points to an empty folder. Use the settings for IIS/Apache or whatever to disable sessions for this new website. Also set some long caching headers on the site, because the content shouldn't change
The second step would be to create an .htaccess file containing the following.
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*) /create.php?path=$1 [L]
This will make sure that if somebody would access an existing image, it will show the image directly without PHP interfering. Every non-existing request will be handled by the create.php script, which is the next thing you should add.
<?php
function NotFound()
{
if (!headers_sent()) {
$protocol = (isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0');
header($protocol . ' 404 Not Found');
echo '<h1>Not Found</h1>';
exit;
}
}
$p = $_GET['path'];
//has path
if (strlen($p)<=1)
NotFound();
$clean = explode('?', $p);
$clean = explode('#', $clean[0]);
$params = explode('/', substr($clean[0], 1)); //drop first /
//I use a check for two, because I dont allow images in the root folder
//I also use the path to determine how it should look
//EG: thumb/125/90/imagecode.jpg
if (count($params)<2)
NotFound();
$type = $params[0];
//I use the type to handle different methods. For this example I only used the full sized image
//You could use the same to handle thumbnails or cropped/watermarked
switch ($type) {
//case "crop":if (Crop($params)) return; else break;
//case "thumb":if (Thumb($params)) return; else break;
case "image":if (Image($params)) return; else break;
}
NotFound();
?>
<?php
/*
Just some example to show how you could create a responds
Since you already know how to create thumbs, I'm not going into details
Array
(
[0] => image
[1] => imagecode.JPG
)
*/
function Image($params) {
$tmp = explode('.', $params[1]);
if (count($tmp)!=2)
return false;
$code = $tmp[0];
//WARNING!! SQL INJECTION
//USE PROPER DB METHODS TO GET REALPATH, THIS IS JUST EXAMPLE
$query = "SELECT realpath FROM images WHERE Code='".$code."'";
//exec query here to $row
$realpath = $row['realpath'];
$f = file_get_contents($realpath);
if (strlen($f)<=0)
return false;
//create folder structure
#mkdir($params[0]);
//if you had more folders, continue creating the structure
//#mkdir($params[0].'/'.$params[1]);
//store the image, so a second request won't access this script
file_put_contents($params[0].'/'.$params[1], $f);
//you could directly optimize the image for web to make it even better
//optimizeImage($params[0].'/'.$params[1]);
//now serve the file to the browser, because even the first request needs to show the image
$finfo = finfo_open(FILEINFO_MIME_TYPE);
header('Content-Type: '.finfo_file($finfo, $params[0].'/'.$params[1]));
echo $f;
return true;
}
?>
I would suggest you to create watermarked images on-the-fly and to cache them at the same time as everybody suggested.
Then you could create a garbage-collector PHP script that will be executed every days (using cron). This script will browse your cache folder to read every image access time. This can done using fileatime() PHP method. Then when a cached wm image has not been accessed within 24 or 48 hours, just delete it.
With this method, you can handle spike periods as images are cached at the first request. AND you will save your HDD space as your garbage-collector script will delete unused images for you.
This method will only work if your server partition has atime updates enabled.
See http://php.net/manual/en/function.fileatime.php
For most scenarios, lazily applying the watermark would probably make most sense (generate the watermarked image on the fly when requested then cache the result) however if you have big spikes in demand you are creating a mechanism to DOS yourself: create the watermarked version on upload.
Considering your HDD storage capacity and Pikes.
I would only create a watermarked image if it is viewed.(so yes on the fly) In that way you dont use to much space with a bunch a files that are or might not be viewed.
I would not watermark thumbnails i would rather make a filter that fake watermark and protect from being saved. That filter would apply to all thumbnails without creating a second image.
In this way all your thumbbails are watermarked (Fake with onther element on top).
Then if one of these thumbnails is viewed it generate a watermarked image (only once) since after its generated you load the new watermarked image.
This would be the most efficient way to deal with your HDD storage and Pikes.
The other option would be to upgrade your hosting services. Godaddy offer unlimited storage and bandwith for about 50$ a year.

Create image, then pass it back

I'm fairly new to php but I'm trying to send an image to a buffer or some sort of temporary place where I can access later. The script I'm calling merges a bunch of images into one, then displays that image (see it in action here - change query parameters to change image). Here's a piece of my code so you have an idea of how that's happening:
$dest = imagecreatefrompng($img0);
$src12 = imagecreatefrompng($img12);
imagecolortransparent($src12, imagecolorat($src12, 0, 0));
//copy and merge
$src12_x = imagesx($src12);
$src12_y = imagesy($src12);
imagecopymerge($dest, $src12, 0, 0, 0, 0, $src12_x, $src12_y, 100);
// Output and free from memory
header('Content-Type: image/png');
imagepng($dest);
imagedestroy($dest);
imagedestroy($src);
However, this is an external script so I'd like to be able to pull that image from another page. I'm not sure what the best way to do it is... temporarily store it or pass the image back through. The one constraint is that the image has to exist before the content of the parent page is loaded. How can I make this happen?
If I understand correctly what you mean;
1) You want to pull the image from another website and save it to disk, you can do this;
file_put_contents("img.png", file_get_contents("URL-TO-IMAGE"));
2) You want to just display it? As the URL aboves headers are to display an image, you can put it right into an IMG tag.
<img src="URL-TO-IMAGE">

resize external images from other websites before loading them?

Iam working on a project , which involves fetching images from various websites and displaying a Thumnail or resized version of orignal image.
As i will be fetching many images at time , this takes more time , As Orignal image files will be loaded.
What i need is given an image url , i need resized version of that image file? So that i need not download the Large orignal image file...
for example : orignal image : 500X800 some 500kb
what i need is : 100X150 some 100kb image file..
Is it possible using Jquery? OR PHP?
Are their any functions like imagecopyresampled(PHP) in Jquery or any plugins?
Well, the big file needs to be downloaded at one point to create the thumbnail.
What you can do, through JQuery, is ask your server for the thumbnail, the server downloads the file, creates the thumbnail and sends back to the client the URL of the thumbnail when the resizing is done. This way, the client will gradually receive thumbnails as they are ready.
Edit After experimenting a bit, I found out that as soon as an img requests a picture, even if you dynamically remove its src attribute, the download continue.
So I decided to write a sample code (there's not much validation and it only works for jpeg, adding the other types would be really easy though). The solution is divided in 3 parts:
HTML
First, I used an empty div with some specific attributes to let jQuery what to load. I need to apologize to Nuria Oliver, she had the first "big picture" I could find on the net. So, here's a sample div:
<div class="thumbnail" data-source="http://www.nuriaoliver.com/pics/nuria1.jpg" data-thumbnail-width="100" data-thumbnail-height= "200"/></div>
I use thumbnail as class to be able to find easily the divs I want. The other data parameters allow me to configure the thumbnail with the source, width and height.
JavaScript / jQuery
Now, we need to locate all these divs requesting thumbnails... using jQuery it is pretty easy. We extract all the data settings and push them in an array. We then feed a PHP page with the query and wait for the response. While doing so, I'm filling the div with some HTML showing the "progress"
<script type="text/javascript">
$(".thumbnail").each(function() {
var img = $(this);
var thumbnailWidth = img.data("thumbnail-width");
var thumbnailHeight = img.data("thumbnail-height");
var thumbnailSource = img.data("source");
var innerDiv = "<div style='width:" + thumbnailWidth + "px; height:" + thumbnailHeight + "px'>Loading Thumbnail<br><img src='loading.gif'></div>";
img.html(innerDiv); // replace with placeholder
var thumbnailParams = {};
thumbnailParams['src'] = thumbnailSource;
thumbnailParams['width'] = thumbnailWidth;
thumbnailParams['height'] = thumbnailHeight;
$.ajax({
url: "imageloader.php",
data: thumbnailParams,
success: function(data) {
img.html("<img src='" + data + "'>");
},
});
})
</script>
PHP
On the PHP side of things, I do a quick test to see if the picture has already been cached (I'm only using the file name, this should be more complicated but it was just to give you an example) otherwise I download the picture, resize it, store it in a thumbnail folder and return the path to jQuery:
<?php
$url = $_GET["src"];
$width = $_GET["width"];
$height = $_GET["height"];
$filename = "thumbnail/" . basename($url);
if(is_file($filename)) // File is already cached
{
echo $filename;
exit;
}
// for now only assume JPG, but checking the extention should be easy to support other types
file_put_contents($filename, file_get_contents($url)); // download large picture
list($originalWidth, $originalHeight) = getimagesize($filename);
$original = imagecreatefromjpeg($filename); // load original file
$thumbnail = imagecreatetruecolor($width, $height); // create thumbnail
imagecopyresized($thumbnail, $original, 0, 0, 0, 0, $width, $height, $originalWidth, $originalHeight); // copy the thumbnail
imagedestroy($original);
imagejpeg($thumbnail, $filename); // overwrite existing file
imagedestroy($thumbnail);
echo $filename;
Browser
So, what does it do exactly? In the Browser, when I open the page I first see:
And as soon as the server is done processing the image, it gets updated automatically to:
Which is a thumbnail version, 100x200 of our original picture.
I hope this covers everything you needed!
PHP Thumb is a good plugin it worked for me and easy to operate.
And the best part is there are many options to select about the output file like its quality, max width for potrait images , max width for landscape images etc..
And we can set permissions like block off server requests, block off domain thumbnails.. etc
Note: this was actually posted by someone , as an answer to this question..But it was deleted.So iam reposting it, as it was useful.
for this to work you need to do some actual image processing which you cant do with js, so some server side language is needed.PHP is an option
If you are not interesting in obfuscating the image source, you may very well rely on an external tool like http://images.weserv.nl/ which takes an original image and allows you to request it in a different size.
If you end up not relying on a global CDN, at least sort out proper caching. Last thing you want to do is resize the same image over and over again for subsequent identical requests - any benefit of image's lower size will probably be negated by processing time.

Adding of Image Layer Fails (GD) PHP

I've installed the GD Library on my Apache just now, and it seems that my script below doesn't work.
I'm trying to add a layer "play.png" to a youtube video thumbnail (http://img.youtube.com/vi/VIDEOID/default.jpg)
I've tried it with many different videoID's but the image doesn't load. There is a message that the graphic couldn't be opened because it contains errors.
I'm opening the file with postimage.php?v=7yV_JtFnIwo
http://img.youtube.com/vi/7yV_JtFnIwo/default.jpg opens correctly too...
Does anyone know where the issue could be?
Thanks in advance!
<?php
// The header line informs the server of what to send the output
// as. In this case, the server will see the output as a .png
// image and send it as such
header ("Content-type: image/png");
// Defining the background image. Optionally, a .jpg image could
// could be used using imagecreatefromjpeg, but I personally
// prefer working with png
$background = imagecreatefromjpeg("http://img.youtube.com/vi/".$_GET['v']."/default.jpg");
// Defining the overlay image to be added or combined.
$insert = imagecreatefrompng("play.png");
// Select the first pixel of the overlay image (at 0,0) and use
// it's color to define the transparent color
imagecolortransparent($insert,imagecolorat($insert,0,0));
// Get overlay image width and hight for later use
$insert_x = imagesx($insert);
$insert_y = imagesy($insert);
// Combine the images into a single output image. Some people
// prefer to use the imagecopy() function, but more often than
// not, it sometimes does not work. (could be a bug)
imagecopymerge($background,$insert,0,0,0,0,$insert_x,$insert_y,100);
// Output the results as a png image, to be sent to viewer's
// browser. The results can be displayed within an HTML document
// as an image tag or background image for the document, tables,
// or anywhere an image URL may be acceptable.
imagepng($background,"",100);
?>
Do not close (avoid whitespaces or newslines) your script with ?> and use NULL instead "".
imagepng($background, NULL);
Then, in imagepng the quality parameter is between 0 and 9, as in http://it.php.net/manual/en/function.imagepng.php.

Categories