saving images in PHP with variable name - php

I am currently developing a web application and need some help.
The functionality is the following: A website connected to a mysql database. You need to select two times brand and then products from that brand solved via interlinked dynamic dropdowns. Based on that selections happen two queries selecting color values from the database, showing them in textfields.
Solved via jquery, PHP and JSON.
Now I have created a section, which will show an image in the color from the selected RGB values from the DB. PHP needs to create the JPG image using the RGB values from the DB and save the image on the server.
When I implement imagecreate in php and hand over the path to jquery to allocate it to a '"#target", I get the issues.
I considered two ways:
a) generate image on the fly, name it 1.jpg and overwrite the image in every instance. Then I run into issues with the browser cache, loading the previous image although the new image is already stored in the folder.
b) generate new images and save them for better performance named with the RGB values (i.e 151|50|22.jpg) and load if already existing, create if not, but there I cannot save the path when a variable is in the imagejpeg() function in PHP?
I can save i)a combination of path elements and a string '1.jpg' and ii)a path made from a pure string but not a path made from a combination of text and a variable carrying the right image name.
Propably it is done with right escaping of the variable???
Errors are:
Warning: imagejpeg(images\rgb\225|151|169.jpg): failed to open stream: No such file or directory in C:\xampp\htdocs\COLOMETRIX\get_swatch_1a.php on line 39
{"decision":"images\rgb\225|151|169.jpg"} this is the Json output
Code is a follows:
<?php
$prod1 = $_GET['q'];
include('db_config.php');
// clear variables
$decision='';
$data='';
// select dataset
$result=$db->query("SELECT R, G, B, Get_Col, Selection
FROM farbdatenbank.farbdatenbank
WHERE Name ='".$prod1."' ")
or die($db->error);
$datensatz=$result->fetch_array(MYSQLI_ASSOC);
// define paths and filename
$file=$datensatz['Get_Col'];
$filename=$file.".jpg";
$path_rgb='images'.DIRECTORY_SEPARATOR.'rgb'.DIRECTORY_SEPARATOR.$filename;
if($datensatz['Selection'] == "Excel"){
// get color values
$R=$datensatz['R'];
$G=$datensatz['G'];
$B=$datensatz['B'];
//check if file already exists
if (file_exists($path_rgb) == true) {
$decision=$path_rgb;
}
else
{
// create new image
$im1=imagecreatetruecolor(150, 70);
$colim1=imagecolorallocate($im1, $R, $G, $B);
imagefill($im1,0,0,$colim1);
$old = 'images'.DIRECTORY_SEPARATOR.'rgb'.DIRECTORY_SEPARATOR.'zzz.jpg';
imagejpeg($im1,$path_rgb,100);
$decision=$path_rgb;
}
}
Else
{
$decision='images'.DIRECTORY_SEPARATOR.'pics'.DIRECTORY_SEPARATOR.$filename;
}
// build output array and encode in JSON format
$data=array("decision"=>$decision);
echo json_encode($data);
mysqli_close($db);
?>
Thanks for your time
Michael

Related

rotate image from database and save to database blob type

Save image to database
$query =$myClass->query("insert into tblImage(document) values(".base64_encode(file_get_contents($_FILES['imageFile']["tmp_name"])).")");
Show image from database
$image =$myClass->query("select document from tblImage where code=1");
$output_bin_string = base64_decode($image[0]['thumbDocument']);
header("Content-Type: image/jpeg");
header("Content-Length: " . strlen($output_bin_string));
echo $output_bin_string;
I can save image to file and then save to database
$image=$myClass->query('select document form tblImage where code=1' );
$source = imagecreatefromstring(base64_decode($image[0]["document"])) ;
$rotate = imagerotate($source,$degrees,0);
imagejpeg($rotate,'tmp/1.jpg');
$image =$myClass->query("update tblImage set document='".base64_encode(file_get_contents('tmp/1.jpg'))."' where code=1");
Question: there is way that rotate image and save to database without save image to file like this
$image=$myClass->query('select document form tblImage where code=1' );
$source = imagecreatefromstring(base64_decode($image[0]["document"])) ;
$rotate = imagerotate($source,$degrees,0);
$image =$myClass->query("update tblImage set document='".base64_encode($rotate)."' where code=1");
This code say error:base64_encode() expects parameter 1 to be string, resource given
Saving files in a database is a bad practice and performs pretty bad when comparing to native file system access or another storage backend like S3. Have a look at this question: Saving images in database mysql
Your approach will cause the data to go through the DB, php and the webserver before it goes to the client. While saving it directly in the file system and keeping a reference in the DB to the file will allow you to send it directly through the webserver when it is requested.
A proper approach is to have one table, lets call it file_storage for example, in the application that keeps the references to files. Then associate the rows as needed: User 1:1 Avatar, User 1:n Photo, Photo n:n Gallery for example. This is DRY, maintains SoC and even allows me to store files in different backends. You can read as well the documentation of this plugin for CakePHP that does exactly what I just described.
For image manipulation I recommend using the Imagine library. Here is an example taken from the documentation:
use Imagine\Image\Box;
use Imagine\Image\Point;
$image->resize(new Box(15, 25))
->rotate(45)
->crop(new Point(0, 0), new Box(45, 45))
->save('/path/to/new/image.jpg');
You should first convert your image resource to a string (by buffering the output into a variable), and then save it to your database like this:
// ... your previous code
$rotate = imagerotate($source,$degrees,0);
// New code starts here
ob_start();
imagejpeg($rotate);
$imageData = ob_get_clean();
$image =$myClass->query("update tblImage set document='".base64_encode($imageData)."' where code=1");
Note that this must be done before sending any output to the client, otherwise ob_start() will fail.

Is more correct consulting images directory or database to count how many there are?

I was trying to insert images into banner dynamically, and is now working correctly. I upload my images and insert on database name of image if there are no validotor errors.
But I'd like to ask you a question that came to my mind, and I'm not finding the answer.
To insert an image, I want to check if the image already exists and also if there are more than 5 images, 5 images because I just want the maximum of 5 images at time on banner.
Im doing this, consulting my directory folder when I save images, and not consulting database.
What do you think better in terms of performance? Or is it the same? Do you see any advantage like Im doing?
heres my code example:
extAlllowed = array('image/jpeg','image/pjpeg','image/png','image/gif');
$myDirectory = ../banner-images/;
if(in_array($img['type'][$i],$extAlllowed))
{
$fi = new FilesystemIterator($myDirectory, FilesystemIterator::SKIP_DOTS);
echo iterator_count($fi);
if(file_exists($myDirectory.$image))
{
echo'Image selected already exist';
}
else if(iterator_count($fi)>=5)
{
echo'You can have only 5 images at time in banner.';
}
else
{
uploadImage($img['tmp_name'][$i],$image,'2000',$myDirectory);
$inseretBanner = $pdo->prepare("INSERT INTO banners (img) VALUES (:img)");
$inseretBanner->bindValue(':img', $image);
$inseretBanner->execute();
echo'Image inserted with sucess';
}
}
Considering having several image files it would be faster to maintain a counter in the database, that contains the current image amount. The FilesystemIterator will internally run over all files to count them, what can lead to poor performance. A simple query (for example: SELECT image_amount FROM users WHERE id = [your current user]) to a database will be faster in most cases.
If you do so, you have to update the counter each time you insert/delete an image in the database.
Hope that helps.

How to treat a PHP image generation script as an image

This is an odd question but I'm stuck on how I would achieve this and I am unable to find any methods of doing so.
I have a simple php script that takes variables (containing file names) from the URL, cleans then and then uses them to generate a single image from the inputted values. This works fine and outputs a new png to the webpage using:
imagepng($img);
I also have a facebook sharing script in PHP that takes a filepath as an input and then shares the image on the users feed where this statement is used to define the image variable:
$photo = './mypic.png'; // Path to the photo on the local filesystem
I don't know how I can link these two together though. I would like to use my generation script as the image to share.
Can anyone point me in the right direction of how to do this? I am not the master of PHP so go easy please.
-Tim
UPDATE
If it helps, here are the links to the two pages on my website containing the outputs. They are very ruff mind you:
The php script generating the image:
http://the8bitman.herobo.com/Download/download.php?face=a.png&color=b.png&hat=c.png
The html page with the img tag:
http://the8bitman.herobo.com/Share.html
Treat it as a simple image:
<img src="http://yourserve/yourscript.php?onlyImage=1" />
yourscript.php
if($_GET['onlyimage']) {
header('Content-type:image/png'); //or your image content type
//print only image
} else {
//print image and text too
}

Most efficient method to pull multiple images from a MySQL db to an Android device

In short, my application needs to pull images from a MySQL db. Since the images pulled will depend on the users location I can't just hardcode image file paths.
So far I've tried using just a PHP script that should allow the app to pull the images from the table into my db but I haven't had any successful results.
In my app this is what I'm using to pull and decode the stream into a bitmap that the phone/app can use:
public static void createIcons(Resources res) throws IOException {
String url1 = " http://mysite.iscool/file-get.php ";
URL ulrn = new URL(url1);
HttpURLConnection con = (HttpURLConnection)ulrn.openConnection();
InputStream is = con.getInputStream();
//end of lines added
markIcon=BitmapFactory.decodeStream(is);
Since I can't seem to return an image to the device from the db using this so far I was wondering what sort of direction I should be going in. I've seen lots of different methods on here explained but I'm not too sure if the method I'm trying to use is even going to work for the purpose I need it to.
Also, I have seen mention of a REST service and other ways to extract images from a mysql db table. So does any one have an suggestions/tutorials/examples of extracting multiple images from a MySQL database?
By the way here is the code I'm using to try to return an image to the device:
<?php
//----------------------------------------------------------
//
//---------------------------------------------------------
// access server
//---------------------------------------------------------
include("fLADB.php");
//
$dbQuery = "SELECT File FROM mark_image_store where imageid =(SELECT MAX(imageid) from
mark_image_store);";
//-----------------------------------------------------------
// selecting into a single element variable
// stores only the first field which is the file data
//-----------------------------------------------------------
$result = mysql_query($dbQuery) or die(mysql_error());
//-----------------------------------------------------------
//reserved for when there is file ext data available.
//to format http headers
//Do not need for use by the phone.
//header("Content-type: image/jpeg");
//if ($ext = "png")
//-------------------------------------------------------------
// use imagejpeg, imagepng?
//-------------------------------------------------------------
header("Content-type: image/png");
print mysql_result($result, 0);
mysql_close();
?>
So after looking at my PHP and Android code can someone please give me some advice on which direction I should be going in next. Should I rework my Android side code and go with a REST service or Webservice or is a PHP script server side enough to handle the image returns.
Any advice/tutorials/or examples would be much appreciated thanks.
You can extract multiple images easily with a single query. But you'll only be able to TRANSFER one image a time, unless you use some kinda of encapsulation like .zip.
If you're serving up the images via HTTP, you'll definitely only be able to serve one picture at a time. There's some tricks where you can serve up a single image with a series of smaller images tiled within it, and display them in restricted-sized divs as tiles/sprites, but that'd require client intervention.

What is the "conventional" way of handling uploaded image names?

So im making a website with an image upload functionality and im storing the image name to the database. I took a screenshot of my mac and wanted to upload this photo "Screen shot 2011-02-18 at 6.52.20 PM.png". Well, thats not a nice name to store in mysql! How do people ususally rename photos in such a way that each photo uploaded has a unique name? Also, how would i make sure i keep the file extension in the end when renaming the photo.
I would drop the extension, otherwise Apache (or equivalent) will run a1e99398da6cf1faa3f9a196382f1fadc7bb32fb7.php if requested (which may contain malicious PHP). I would also upload it to above the docroot.
If you need to to make the image accessible above the docroot, you can store a safe copy that is ran through image functions or serve it from some PHP with header('Content-Type: image/jpeg') for example and readfile() (not include because I can embed PHP in a GIF file).
Also, pathinfo($path, PATHINFO_EXTENSION) is the best way to get an extension.
Ensure you have stored a reference to this file with original filename and other meta data in a database.
function getUniqueName($originalFilename) {
return sha1(microtime() . $_SERVER['REMOTE_ADDR'] . $originalFilename);
}
The only way this can generate a duplicate is if one user with the same IP uploads the same filename more than once within a microsecond.
Alternatively, you could just use the basename($_FILES['upload']['tmp_name']) that PHP assigns when you upload an image. I would say it should be unique.
Hash the image name. Could be md5, sha1 or even a unix timestamp.
Here is an (untested) example with a random number (10 to 99)
<?php
function generate_unique_name($file_name)
{
$splitted = split(".", $file_name);
return time() . rand(10,99) . "." . $splitted[count($splitted)-1];
}
?>
You could use an image table like:
id: int
filename: varchar
hash: varchar
format: enum('jpeg', 'png')
The hash can be something like sha1_file($uploaded_file) and used to make sure duplicate images aren't uploaded. (So you could have multiple entries in the image table with the same hash, if you wanted.) The id is useful so you can have integer foreign key links back to the image table.
Next store the images in either:
/image/$id.$format
or
/image/$hash.$format
The second format via the hash would make sure you don't duplicate image data. If you are dealing with lots of images, you may want to do something like:
/image/a/b/c/abcdef12345.jpg
where you use multiple layers of folders to store the images. Many file systems get slowed down with too many files in a single directory.
Now you can link to those files directly, or set up a URL like:
/image/$id/$filename
For example:
/image/12347/foo.jpg
The foo.jpg comes from whatever the user uploaded. It is actually ignored because you look up via the id. However, it makes the image have a nice name if the person chooses to download it. (You may optionally validate that the image filename matches after you look up the id.)
The above path can be translated to image.php via Apache's MultiView or ModRewrite. Then you can readfile() or use X-SendFile (better performance, but not always available) to send the file to the user.
Note that if you don't have X-SendFile and don't want to process things through PHP, you could use a RewriteRule to convert /image/$hash/foo.jpg into /image/a/b/c/$hash.jpg.

Categories