Images rotate automatically - php

I have a iPhone app that uploads pictures to my server. One major issue I am having is a rotating one.
For some reason if I upload a picture from my iPhone, some pictures will automatically rotate. The one's that do get rotated are the ones in portrait mode. I have no code in my script that rotates the images.
How does a server exactly process tall images? Should I modify my php file to check to rotate it ahead after it automatically rotates? Should I code something in my iPhone app that will check this?
Any help is appreciated!
PS: If you need code, feel free to ask!

Some pictures(jpg) have exif data that tells the position the camera was when the picture was shot.
Take a look at http://www.php.net/manual/en/function.exif-read-data.php#76964
You may rotate the pictures server-side like this

Or a better way is to use this library
https://github.com/Intervention/image
And simply use like this-
$img = Image::make('foo.jpg')->orientate();
More can be found here.

When you take a picture your phone saves any rotation metadata in EXIF headers. When you upload the image to your server, that metadata is still sitting there but it's your job to apply it to the image to rotate it (if you want). In PHP you can use a function called exif_read_data:
function correctImageOrientation($filename)
{
$exif = exif_read_data($filename);
if ($exif && isset($exif['Orientation'])) {
$orientation = $exif['Orientation'];
if ($orientation != 1) {
$img = imagecreatefromjpeg($filename);
$deg = 0;
switch ($orientation) {
case 3:
$deg = 180;
break;
case 6:
$deg = 270;
break;
case 8:
$deg = 90;
break;
}
if ($deg) {
$img = imagerotate($img, $deg, 0);
}
imagejpeg($img, $filename, 95);
}
}
}
To use it simply call the function after you save the file. For more info and an additional PHP solution see the original source.

Related

How to install small PHP scripts for tools into pages of an existing website?

First of all, I'm a physician and not a technical expert whatsoever like you, so please bear with me :D
I want to build a website that offers online tools like "email extracting", "image resizing", etc, and I was wondering how to install tools with small PHP scripts like 1-2 .php files, and have them on different pages in the existing website "internettoolkits.com"?
Other tools I found, have more folders and files and most videos talk about databases and playing with file managers, and for those, I decided to create a subdomain for each, following the advises of creating new database and updating the file manager since they have an admin and user areas. (according to my understanding)
But for the small ones that don't require admin and user areas, like email extracting tool, can I have the php scripts added to a page/post in wordpress like with using HTML scripts? I tried the HTML scripts and they work fine (you can see examples on that website)
Do I insert them in specific files in the file manager and how to do it to make it appear in a designated page called "Thumbnail Generator Tool" for example?
Do I need to create a specific database for each of those small tools or not?
I tried using plugins (code snippet) and (insert PHP code snippet) and both didn't work
Example of tool to have: Thumbnail generator tool that have 2 files below:
first file (image.class.php)
<?php
###############################################################
# Thumbnail Image Class for Thumbnail Generator
###############################################################
# For updates visit http://www.zubrag.com/scripts/
###############################################################
class Zubrag_image {
var $save_to_file = true;
var $image_type = -1;
var $quality = 100;
var $max_x = 100;
var $max_y = 100;
var $cut_x = 0;
var $cut_y = 0;
function SaveImage($im, $filename) {
$res = null;
// ImageGIF is not included into some GD2 releases, so it might not work
// output png if gifs are not supported
if(($this->image_type == 1) && !function_exists('imagegif')) $this->image_type = 3;
switch ($this->image_type) {
case 1:
if ($this->save_to_file) {
$res = ImageGIF($im,$filename);
}
else {
header("Content-type: image/gif");
$res = ImageGIF($im);
}
break;
case 2:
if ($this->save_to_file) {
$res = ImageJPEG($im,$filename,$this->quality);
}
else {
header("Content-type: image/jpeg");
$res = ImageJPEG($im, NULL, $this->quality);
}
break;
case 3:
if (PHP_VERSION >= '5.1.2') {
// Convert to PNG quality.
// PNG quality: 0 (best quality, bigger file) to 9 (worst quality, smaller file)
$quality = 9 - min( round($this->quality / 10), 9 );
if ($this->save_to_file) {
$res = ImagePNG($im, $filename, $quality);
}
else {
header("Content-type: image/png");
$res = ImagePNG($im, NULL, $quality);
}
}
else {
if ($this->save_to_file) {
$res = ImagePNG($im, $filename);
}
else {
header("Content-type: image/png");
$res = ImagePNG($im);
}
}
break;
}
return $res;
}
function ImageCreateFromType($type,$filename) {
$im = null;
switch ($type) {
case 1:
$im = ImageCreateFromGif($filename);
break;
case 2:
$im = ImageCreateFromJpeg($filename);
break;
case 3:
$im = ImageCreateFromPNG($filename);
break;
}
return $im;
}
// generate thumb from image and save it
function GenerateThumbFile($from_name, $to_name) {
// if src is URL then download file first
$temp = false;
if (substr($from_name,0,7) == 'http://') {
$tmpfname = tempnam("tmp/", "TmP-");
$temp = #fopen($tmpfname, "w");
if ($temp) {
#fwrite($temp, #file_get_contents($from_name)) or die("Cannot download image");
#fclose($temp);
$from_name = $tmpfname;
}
else {
die("Cannot create temp file");
}
}
// check if file exists
if (!file_exists($from_name)) die("Source image does not exist!");
// get source image size (width/height/type)
// orig_img_type 1 = GIF, 2 = JPG, 3 = PNG
list($orig_x, $orig_y, $orig_img_type, $img_sizes) = #GetImageSize($from_name);
// cut image if specified by user
if ($this->cut_x > 0) $orig_x = min($this->cut_x, $orig_x);
if ($this->cut_y > 0) $orig_y = min($this->cut_y, $orig_y);
// should we override thumb image type?
$this->image_type = ($this->image_type != -1 ? $this->image_type : $orig_img_type);
// check for allowed image types
if ($orig_img_type < 1 or $orig_img_type > 3) die("Image type not supported");
if ($orig_x > $this->max_x or $orig_y > $this->max_y) {
// resize
$per_x = $orig_x / $this->max_x;
$per_y = $orig_y / $this->max_y;
if ($per_y > $per_x) {
$this->max_x = $orig_x / $per_y;
}
else {
$this->max_y = $orig_y / $per_x;
}
}
else {
// keep original sizes, i.e. just copy
if ($this->save_to_file) {
#copy($from_name, $to_name);
}
else {
switch ($this->image_type) {
case 1:
header("Content-type: image/gif");
readfile($from_name);
break;
case 2:
header("Content-type: image/jpeg");
readfile($from_name);
break;
case 3:
header("Content-type: image/png");
readfile($from_name);
break;
}
}
return;
}
if ($this->image_type == 1) {
// should use this function for gifs (gifs are palette images)
$ni = imagecreate($this->max_x, $this->max_y);
}
else {
// Create a new true color image
$ni = ImageCreateTrueColor($this->max_x,$this->max_y);
}
// Fill image with white background (255,255,255)
$white = imagecolorallocate($ni, 255, 255, 255);
imagefilledrectangle( $ni, 0, 0, $this->max_x, $this->max_y, $white);
// Create a new image from source file
$im = $this->ImageCreateFromType($orig_img_type,$from_name);
// Copy the palette from one image to another
imagepalettecopy($ni,$im);
// Copy and resize part of an image with resampling
imagecopyresampled(
$ni, $im, // destination, source
0, 0, 0, 0, // dstX, dstY, srcX, srcY
$this->max_x, $this->max_y, // dstW, dstH
$orig_x, $orig_y); // srcW, srcH
// save thumb file
$this->SaveImage($ni, $to_name);
if($temp) {
unlink($tmpfname); // this removes the file
}
}
}
?>
Second file named (thumb.php)
<?php
###############################################################
# Thumbnail Image Generator 1.3
###############################################################
# Visit http://www.zubrag.com/scripts/ for updates
###############################################################
// REQUIREMENTS:
// PHP 4.0.6 and GD 2.0.1 or later
// May not work with GIFs if GD2 library installed on your server
// does not support GIF functions in full
// Parameters:
// src - path to source image
// dest - path to thumb (where to save it)
// x - max width
// y - max height
// q - quality (applicable only to JPG, 1 to 100, 100 - best)
// t - thumb type. "-1" - same as source, 1 = GIF, 2 = JPG, 3 = PNG
// f - save to file (1) or output to browser (0).
// Sample usage:
// 1. save thumb on server
// http://www.zubrag.com/thumb.php?src=test.jpg&dest=thumb.jpg&x=100&y=50
// 2. output thumb to browser
// http://www.zubrag.com/thumb.php?src=test.jpg&x=50&y=50&f=0
// Below are default values (if parameter is not passed)
// save to file (true) or output to browser (false)
$save_to_file = true;
// Quality for JPEG and PNG.
// 0 (worst quality, smaller file) to 100 (best quality, bigger file)
// Note: PNG quality is only supported starting PHP 5.1.2
$image_quality = 100;
// resulting image type (1 = GIF, 2 = JPG, 3 = PNG)
// enter code of the image type if you want override it
// or set it to -1 to determine automatically
$image_type = -1;
// maximum thumb side size
$max_x = 100;
$max_y = 100;
// cut image before resizing. Set to 0 to skip this.
$cut_x = 0;
$cut_y = 0;
// Folder where source images are stored (thumbnails will be generated from these images).
// MUST end with slash.
$images_folder = '/www/images/';
// Folder to save thumbnails, full path from the root folder, MUST end with slash.
// Only needed if you save generated thumbnails on the server.
// Sample for windows: c:/wwwroot/thumbs/
// Sample for unix/linux: /home/site.com/htdocs/thumbs/
$thumbs_folder = '/www/thumbs/';
///////////////////////////////////////////////////
/////////////// DO NOT EDIT BELOW
///////////////////////////////////////////////////
$to_name = '';
if (isset($_REQUEST['f'])) {
$save_to_file = intval($_REQUEST['f']) == 1;
}
if (isset($_REQUEST['src'])) {
$from_name = urldecode($_REQUEST['src']);
}
else {
die("Source file name must be specified.");
}
if (isset($_REQUEST['dest'])) {
$to_name = urldecode($_REQUEST['dest']);
}
else if ($save_to_file) {
die("Thumbnail file name must be specified.");
}
if (isset($_REQUEST['q'])) {
$image_quality = intval($_REQUEST['q']);
}
if (isset($_REQUEST['t'])) {
$image_type = intval($_REQUEST['t']);
}
if (isset($_REQUEST['x'])) {
$max_x = intval($_REQUEST['x']);
}
if (isset($_REQUEST['y'])) {
$max_y = intval($_REQUEST['y']);
}
if (!file_exists($images_folder)) die('Images folder does not exist (update $images_folder in the script)');
if ($save_to_file && !file_exists($thumbs_folder)) die('Thumbnails folder does not exist (update $thumbs_folder in the script)');
// Allocate all necessary memory for the image.
// Special thanks to Alecos for providing the code.
ini_set('memory_limit', '-1');
// include image processing code
include('image.class.php');
$img = new Zubrag_image;
// initialize
$img->max_x = $max_x;
$img->max_y = $max_y;
$img->cut_x = $cut_x;
$img->cut_y = $cut_y;
$img->quality = $image_quality;
$img->save_to_file = $save_to_file;
$img->image_type = $image_type;
// generate thumbnail
$img->GenerateThumbFile($images_folder . $from_name, $thumbs_folder . $to_name);
?>
This is not nearly as easy as you may think.
To answer your question:
I want to build a website that offers online tools like "email extracting", "image resizing", etc, and I was wondering how to install tools with small PHP scripts like 1-2 .php files, and have them on different pages in the existing website
For each tool you want to integrate, you will want to create a separate plugin. This plugin can be as simple as a single PHP file but I'm guessing they are going to be more complex.
Some of the plugins you create will need admin pages unless you are planning on running them just on your own website. In these cases, it's safe to use a config file and just set the needed options there. it's not ideal, but it is quicker than creating an admin page.
Yes, some of your plugins will need database access. You wouldn't create a new database just for them though. Whenever possible, work within WordPress' existing DB structure. You have a lot of different tools at your disposal for saving off options both permanently and temporarily. As a last option, you could create your own table in the database just for your plugins but I would not do that unless there is absolutely no way to use the existing structures.
For integrating them into pages, the easy way is to use short codes. The modern way is to use Gutenberg blocks. Blocks take more time to code but if you are planning on selling/distributing these tools, people will expect them. If you are just using these on your own, a short-code would probably suffice.
Sorry I don't have a better answer for you but honestly, what you are asking is a lot of work. (and I've not even touched on auditing the code for security issues before integrating it into your site!)
Cheers! :)
=C=

Images Rotating

I have a very strange problem.
On my website there is a file field that will allow the users to upload their profile picture.
It gets uploaded using JQuery and it gets saved using PHP.
If I upload from a PC / MAC / iPhone then there is no problem whatsoever, however if I upload using an Android device the image gets rotated.
The rotation is not even consistent, it could be 90% 180% or 270%, this happens when taking a image or selecting from the Gallery.
Why would this happen? and is there a possible fix?
This solved the issue
From the PHPDocs
<?php
$image = imagecreatefromstring(file_get_contents($_FILES['image_upload']['tmp_name']));
$exif = exif_read_data($_FILES['image_upload']['tmp_name']);
if(!empty($exif['Orientation'])) {
switch($exif['Orientation']) {
case 8:
$image = imagerotate($image,90,0);
break;
case 3:
$image = imagerotate($image,180,0);
break;
case 6:
$image = imagerotate($image,-90,0);
break;
}
}
// $image now contains a resource with the image oriented correctly
?>

Send image from android - receives rotated picture on server

I am trying to write an android app that takes a picture and saves it to a server. The problem is that every picture I take is rotated with -90 degrees when saved on the server. Any idea how I can rotate the picture in php or why it ends up being rotated?
This is how my php file looks like:
<?php
$file_path = "photos/";
$img = $_REQUEST['base64'];
$name=$_REQUEST['ImageName'];
// Decode Image
$binary=base64_decode($img);
$success = file_put_contents($file_path.$name, $binary);
if($success === false) {
echo "Couldn't write file";
} else {
echo "Wrote $success bytes";
}
echo $name;
?>
It isn't a server side issue, every smartphone can apply a different orientation to the camera images.
When you receive the image you have to access to its metadata (exif data si the exact name) to verify its rotation and other properties. Then you should apply to the picture the transformations you need.
This should be a good startpoint to read exif data with PHP: http://php.net/manual/en/function.exif-read-data.php
Maybe it has something to do with image orientation.
Try this
$exif = exif_read_data($file_path.$name);
$ort = $exif['IFD0']['Orientation'];
switch($ort)
{
case 3: // 180 rotate left
$image->imagerotate($file_path.$name, 180, -1);
break;
case 6: // 90 rotate right
$image->imagerotate($file_path.$name, -90, -1);
break;
case 8: // 90 rotate left
$image->imagerotate($file_path.$name, 90, -1);
break;
}

Transform .jpg, .jpeg or .gif to .png without saving them on machine

Is it possible to transform a .jpg, .jpeg or .gif image to .png in php without saving the image in your computer?
Something like:
function read_image($filename, $extension) {
switch($extension) {
case '.png':
$image = imagecreatefrompng($filename);
break;
case '.jpg': case '.jpeg':
$unTransformed = imagecreatefromjpeg($filename);
$image = transform($unTransformed);
break;
case '.gif':
$unTransformed = imagecreatefromgif($filename);
$image = transform($unTransformed);
break;
return $image;
}
}
function transform($unTransformed) {
// Some magic here without actually saving the image to your machine when transforming
return $transformed;
}
I honestly couldn't find an answer for this. Also note that GD is mandatory.
Using output buffering and capturing the output of imagepng should work, like this:
function transform($unTransformed) {
ob_start();
imagepng($unTransformed);
$transformed = ob_get_clean();
return $transformed;
}
Of course, this is assuming you actually want a variable containing a png bytestream of your image file. If the only purpose is to output it anyways, don't bother and do as Marty McVry suggests.
Directly from the PHP manual: (imagepng()-function, which outputs a PNG image to either the browser or a file)
header('Content-Type: image/png');
$transformed = imagepng($untransformed);
You might encounter a problem sending the headers along, so it's possibly necessary to output the headers somewhere else or transform the stream created by imagepng to a base64-string and display the image like that, depending on the rest of your code.

Prevent imagejpeg() from saving EXIF data for images (spec. FileDateTime)

Our server is saving EXIF data to every file saved with imagejpeg(). As far as I know, this is not the default behavior (or even possible, from what I've read). But, it is occurring, and due to the FileDateTime information being included (and using the time of save), it is breaking functionality in our upload/approval system (md5_file() returns a different value for the exact same image due to FileDateTime always being different).
Is there a way to prevent imagejpeg() from saving EXIF data for images by default?
Server Information
CentOS 5
Parallels Plesk Panel 10.4.4
GD Version: bundled (2.0.34 compatible)
PHP 5.3
Code
<?php
public function upload_book_cover($book, $cover, $filename = NULL, $approved = NULL){
global $c_consummo, $user;
$approved = bool($approved, true, true);
if(filesize($cover)>5242880){
return false; // Too large;
}
$max_width = 450;
$cover_info = getimagesize($cover);
if(!$this->is_valid_book_cover_type($cover_info['mime'])){
return false; // Invalid image type
}
$width = $cover_info[0];
$height = $cover_info[1];
if($width<200){
return false; // Too small
} elseif($width>1500){
return false; // Too wide
}
$original_cover = false;
switch($cover_info[2]){
case IMAGETYPE_GIF:
$original_cover = imagecreatefromgif($cover);
break;
case IMAGETYPE_JPEG:
$original_cover = imagecreatefromjpeg($cover);
break;
case IMAGETYPE_PNG:
$original_cover = imagecreatefrompng($cover);
break;
case IMAGETYPE_BMP:
$original_cover = imagecreatefrombmp($cover);
break;
}
if(!$original_cover){
return false; // Unsupported type
}
if($width>$max_width){
$new_width = $max_width;
} else {
$new_width = $width;
}
$new_height = round($height*($new_width/$width));
$new_cover = imagecreatetruecolor($new_width, $new_height);
if(!$new_cover){
return false; // Could not create true color image
}
if(!imagecopyresampled($new_cover, $original_cover, 0, 0, 0, 0, $new_width, $new_height, $width, $height)){
return false; // Could not copy image
}
if(!imagejpeg($new_cover, $cover, 100)){
return false; // Image could not be saved to tmp file
// This is adding *new* EXIF data to images by itself
}
$file_hash = md5_file($cover);
$duplicate_book_cover = $this->find_duplicate_book_cover($book, $file_hash);
if($duplicate_book_cover){
return $duplicate_book_cover;
}
$file_id = $c_consummo->upload_file($cover, $filename);
...
}
It looks like you have tried several things here, but lets try one more.
Do you EVER need EXIF information in your application?
If not lets take out support for EXIF and see if that completely removes it.
If it does not remove it, then perhaps the functions are reading it from the existing photos and then just blindly including it in the file that is written.
You can know for sure by printing out the EXIF information at each step of process
No idea why EXIF data is being written - so the following may help you remove it.
One suggestion is to run something as a command on the server - it will need some installation: http://hacktux.com/read/remove/exif - then run throuhg EXEC from PHP.
There's also solution posted here that uses ImageMagick if you also have that installed (or cen get it installed: Remove EXIF data from JPG using PHP (but note warning about colour)
Otherwise, the other suggestion is as above, try turning off the EXIT extension.
Sorry if they don't help, but you did ask for any suggestions.
Apparently, GD doesn't like when the path to the input / output file is the same, but the credit isn't mine. To fix, use a new (tmp) file to save the newly created image to:
<?php
...
if(!imagecopyresampled($new_cover, $original_cover, 0, 0, 0, 0, $new_width, $new_height, $width, $height)){
return false; // Could not copy image
}
// Create a tmp file.
$cover_new = tempnam('/tmp', 'cover-');
// Use $cover_new instead of $cover
if(!imagejpeg($new_cover, $cover_new, 100)){
return false; // Image could not be saved to tmp file
}
// Use $cover_new instead of $cover
$file_hash = md5_file($cover_new);
$duplicate_book_cover = $this->find_duplicate_book_cover($book, $file_hash);
if($duplicate_book_cover){
return $duplicate_book_cover;
}
// Use $cover_new instead of $cover
$file_id = $c_consummo->upload_file($cover_new, $filename);
...
Read this, maybe it will help:
http://www.php.net/manual/en/function.imagecreatefromjpeg.php#65656
and this:
http://www.sentex.net/~mwandel/jhead/usage.html
You could possibly convert the jpeg to a gif first, then convert the gif back to a jpeg. In doing so, my understanding is that you would destroy the EXIF data. It's a hack, but it should work.
The only thing that spring to mind is, that you could ignore the EXIF data and just make your hash from something else? My suggestion would be to try either hashing the raw output without saving to a file (here outputting in gif format -which makes a smaller, 8-bit image for performance- to an output buffer and hashing the buffer content)
if(!imagecopyresampled(...)) {...}
ob_start();
imagegif($new_cover);
$file_hash = md5(ob_get_contents());
ob_end_clean();
if(!imagejpeg($new_cover, $cover, 100)) {...}
Or you could build a string containing only the pixel information and hash that (here done by accessing each pixel and appending its value to a string, in reverse for performance)
$pixels = '';
for($x=$new_width-1; $x>=0; $x--) {
for($y=$new_height-1; $y>=0; $y--) {
$pixels .= imagecolorat($new_cover, $x, $y);
}
}
$file_hash = md5($pixels);
For performance, you could also choose only to take samples from the image, as this should work just as well or maybe even better (here sampling every 5th pixel of every 5th row)
$pixels = '';
for($x=$new_width-1; $x>=0; $x-=5) {
for($y=$new_height-1; $y>=0; $y-=5) {
$pixels .= imagecolorat($new_cover, $x, $y);
}
}
$file_hash = md5($pixels);
I hope some of this will work (as I can't test it right now) or at least will help you find the way that works for you :)
This is a bit of a hack, but it will work, just do this after your switch() statement:
$original_cover = imagerotate($original_cover,360,0);
GD will strip any EXIF data out, as it doesn't support it.
You could try using imagecreatefromjpeg on the image created with imagejpeg and replacing with the newly created one.
$res = imagecreatefromjpeg($filename) to load the image, then imagejpeg($res, $filename, QUALITY)to rerender it.
You can use imagemagick too:
$img = new Imagick($image);
$img->stripImage();
$img->writeImage($image);
$img->clear();
$img->destroy();
Your PHP must be compiled in with --enable-exif.
Try to disable globally EXIF functionality by recompiling PHP without this option.

Categories