Imagick PHP (How to resize each image from database?) - php

I have been trying to resize each image from database before pushing it into an array. The array contains the image path(URL) where I would like to display the resize image onto a grid view as the original images are too big and takes too long to load, hence the resizing. I have been figuring out the logic and still couldn't solve it. Could anyone help me with this? My database contains columns 'photo' and 'location'.
getphoto.php
<?php
require_once('dbConnect.php');
$sql = "select * from volleyupload1";
$res = mysqli_query($con, $sql);
$result = array();
while ($row = mysqli_fetch_array($res)) {
foreach ($result as $row['photo']) {
$imagick = new Imagick($row['photo']);
$imagick->thumbnailImage(300, 300, true, true);
header("Content-Type: image/jpg");
// echo $imagick;
}
array_push($result, array('url' => $row['photo'], 'location' => $row['location']));
// $test = $row['photo'];
// foreach ($result as $row['photo']){
// $imagick = new Imagick($row['photo']);
// $imagick->thumbnailImage(300, 300, true, true);
// header("Content-Type: image/jpg");
// echo $imagick;
//
// }
}
echo json_encode(array("result" => $result));
mysqli_close($con);

I don't get the difference between 'photo' and 'location'. To the browser you should only send URLs not local filepaths.
Anyway, you need to store the thumbnail image to a new file and then return the url to this file instead of the original one.
Could look like this:
while ($row = mysqli_fetch_array($res)) {
$imagick = new Imagick($row['photo']);
$imagick->thumbnailImage(300, 300, true, true);
$thumb_path = $row['photo'] . '.thumb.jpg';
$thumb = fopen($thumb_path, 'w'); //open new filehandle to write the thumb
$imagick->writeImageFile($thumb);
fclose($thumb);
array_push($result, array('url' => $thumb_path, 'location' => $row['location']));
}
$thumb_path needs to be a local file path. To the browser you need to send a URL which is reachable from the internet

Related

Google Cloud Vision save imagen after detect objects

I am trying to save a image in my database after detect objects with Google cloud vision. I am using php, framework laravel, this is my code,
function detect_object($imagen){
$path = $imagen->getRealPath();
$imageAnnotator = new ImageAnnotatorClient(['credentials' => base_path('credentials.json')]);
$output = imagecreatefromjpeg($path);
list($width, $height, $type, $attr) = getimagesize($path);
# annotate the image
$image = file_get_contents($path);
$response = $imageAnnotator->objectLocalization($image);
$objects = $response->getLocalizedObjectAnnotations();
foreach ($objects as $object) {
$name = $object->getName();
$score = $object->getScore();
$vertices = $object->getBoundingPoly()->getNormalizedVertices();
// printf('%s (confidence %f)):' . PHP_EOL, $name, $score);
// print('normalized bounding polygon vertices: ');
// foreach ($vertices as $vertex) {
// printf(' (%f, %f)', $vertex->getX(), $vertex->getY());
// }
// print(PHP_EOL);
$vertices_finales = [];
foreach ($vertices as $vertex) {
array_push($vertices_finales, ($vertex->getX() * $width));
array_push($vertices_finales, ($vertex->getY() * $height));
}
imagepolygon($output, $vertices_finales, (sizeof($vertices_finales) / 2), 0x00ff00);
imagestring($output, 5, ($vertices_finales[0] + 10), ($vertices_finales[1] + 10), $name, 0x00ff00);
}
header('Content-Type: image/jpeg');
imagejpeg($output);
imagedestroy($output);
$imageAnnotator->close();
}
Could you help me?
Thanks
I'm going to assume that you want to grab the raw binary generated by imagejpeg() after processing?
The only way i know how to do that is using output buffers.
instead of:
<?php
header('Content-Type: image/jpeg');
imagejpeg($output);
imagedestroy($output);
$imageAnnotator->close();
Do:
<?php
ob_start();
imagejpeg($output);
$imgData = ob_get_clean();
# Do what you want with imgData, like insert into a binary field in a db, write to disk, etc
imagedestroy($output);
$imageAnnotator->close();
If you also want to output the image to the browser, return $imgData from your detect_object() function and echo it to the browser
<?php
$imgData = detect_object($imagen);
header('Content-Type: image/jpeg');
echo $imgData

Ideas on mass image conversion - why is this running out of memory?

I am trying to:
Loop through ~4000 folders.
Get the images within each folder.
Create several different sizes of images and save the new images to the same folder.
My code (below) for this is working, but after it has done only a few folders (maybe 50) it gives an "out of memory error". It takes about 5 minutes to get to this stage.
I have tried increasing any max memory size I can find in php.ini (to 1000MB), but I still get the same "out of memory error" and at the same value.
My server is showing as hardly doing anything (16 core/36gig ram) so I don't think it is a hardware limit.
Sorry if this is not the right place to ask this question, but does anyone have any ideas how I can re-size (and rename) all these images?
The code I am using is below:
ini_set('max_execution_time', 60000);
define('IMAGEWidth', 800);
define('IMAGEHeight', 800);
define('THUMBNAILWidth', 109);
define('THUMBNAILHeight', 164);
define('THUMBNAILWidthLARGE', 180);
define('THUMBNAILHeightLARGE', 270);
define('MAX_BYTE_IMAGE_SIZE', 83886080); // max files size allowed = 10MB
//** ============ images sizes ===============
// small thumb
$imageSize_arr[] = array('image_resize' => true, 'image_x' => THUMBNAILWidth, 'image_ratio_y' => true, 'jpeg_quality' => 80, 'image_min_width' => 100, 'image_unsharp_amount' => 80, 'file_name_body_add' => '_thumb');
// normal thumb
$imageSize_arr[] = array('image_resize' => true, 'image_x' => THUMBNAILWidthLARGE, 'image_ratio_y' => true, 'jpeg_quality' => 80, 'image_min_width' => 100, 'image_unsharp_amount' => 80, 'file_name_body_add' => '_largethumb');
// full size image
$imageSize_arr[] = array('image_resize' => true, 'image_x' => IMAGEWidth, 'image_ratio_y' => true, 'jpeg_quality' => 80, 'image_min_width' => 100, 'image_unsharp_amount' => 80);
//origional file
$imageSize_arr[] = array('image_resize' => false, 'file_name_body_add' => '_origional');
require('upload.class.php');
$path = '/var/www/import/propertyimages/';
$results = scandir($path);
//echo '<pre>';
//print_r($results);
//echo '</pre>';
foreach ($results as $result) {
if ($result === '.' || $result === '..') {continue;}
if (is_dir($path.$result)) {
$path2 = $path.$result;
echo '<h1>'.$path2.'</h1><br>';
$results2 = scandir($path2);
//echo '<pre>';
//print_r($results2);
//echo '</pre>';
foreach ($results2 as $image) {
if ($image === '.' || $image === '..') {continue;}
//echo 'image = '.$path2.'/'.$image.'<br>';
$sourcePath = $path2.'/'.$image;
//global $imageSize_arr;
$handle = new upload($sourcePath); // initiate upload class and provide file to be altered
$fileName = $image;
if ($handle->uploaded) {
foreach ($imageSize_arr as $size_arr){ // get image sizes from config.php
$handle->file_new_name_body = $fileName; // set the file name
$handle->file_overwrite = true;
$handle->file_max_size = MAX_BYTE_IMAGE_SIZE; // get max image sizes from config.php
$handle->allowed = array('image/*'); // set allowed file types
foreach($size_arr as $key=>$value){ // get image convertion types from $imageSize_arr/$size_arr
$handle->$key = $value;
}
$handle->process($path2.'/'); // prosess the image and save to specified location
}
// check if all went well
if ($handle->processed) {
$handle->clean();
$handle->error;
echo 'done<br>';
}
else {
echo $handle->error;
echo 'error<br>';
}
}
else {echo '<strong>ERROR</strong>'.$handle->error.'<br>';}
}
}
}
Might or might not be of some help: Clearing Memory
You can also add this to your script to increase your memory limit:
ini_set('memory_limit', '2048M');

Cannot display blob image from database using PHP

I am not able to get my broswer to display an image from the database(stored as blob). I have tried
header("Content-type: image/jpeg");
echo '';
But it is still not able to display on the browser.
getImage.php
<?php
require_once 'php-activerecord/ActiveRecord.php';
ActiveRecord\Config::initialize(function($cfg) {
$cfg->set_model_directory('models');
$cfg->set_connections(array(
'development' => 'mysql://root:mysql#localhost/BondingTogether'));
});
$id = addslashes($_REQUEST['id']);
$row = food::find_by_foodid($id);
$image = $row->image;
//$image = ""
//header("Content-Type: image/jpg");
header("Content-type: image/jpeg");
//echo '<img src="data:image/jpeg;base64,'.base64_encode($image).'"/>';
echo $image;
//echo base64_decode($image);
Adding to the database
<?php
require_once 'php-activerecord/ActiveRecord.php';
ActiveRecord\Config::initialize(function($cfg) {
$cfg->set_model_directory('models');
$cfg->set_connections(array(
'development' => 'mysql://root:mysql#localhost/BondingTogether'));
});
//files
$file = $_FILES['foodimage']['tmp_name'];
if (!isset($file)) {
}
else {
//$image = addslashes(file_get_contents($_FILES['foodimage']['tmp_name']));
$image_name = addslashes($_FILES['foodimage']['tmp_name']);
$image_size = getimagesize($_FILES['foodimage']['tmp_name']);
if ($image_size == FALSE) {
die('Please select an image file');
} else {
}
}
$image = addslashes(file_get_contents($_FILES['foodimage']['tmp_name']));
//$image = chunk_split(base64_encode(file_get_contents("image.jpg")));
Food::create(array(
'xcoord' => $_POST['XCoord']
, 'ycoord' => $_POST['YCoord']
, 'title' => $_POST['title']
, 'category' => $_POST['cat']
, 'description' => $_POST['desc']
, 'image' => $image
));
You should not be using addslashes() when storing image data in your DB. A better alternative is to insert the image data with base64_encode(), and base64_decode() it when you output it. A simple search will find plenty of good answers to this and similar questions

Converting multipage pdf to multi images

I am trying to convert a multipage PDF File to images by using PHP Image magic extension.The problem is that instead of getting images corresponding to each page of the file, I am getting the last page of pdf as the output image. Here is the code:
$handle = fopen($imagePath, "w");
$img1 = new Imagick();
$img1->setResolution(300,300);
$img1->readImage(path to pdf file);
$img1->setColorspace(imagick::IMGTYPE_GRAYSCALE);
$img1->setCompression(Imagick::COMPRESSION_JPEG);
$img1->setCompressionQuality(80);
$img1->setImageFormat("jpg");
$img1->writeImageFile($handle);
What am I doing wrong?The convert command on commandline with the same parameters works.
Try something like this instead:
$images = new Imagick("test.pdf");
foreach($images as $i=>$image) {
$image->setResolution(300,300);
//etc
$image->writeImage("page".$i.".jpg");
}
Try writeImages function. It creates each page as one image and it gives file names for multiple images like this: yourimagename, yourimagename-1, yourimagename-2.... It increases automatically from 0 to your numberofpagesinPdf-1.
The code looks like this:
$imagick = new Imagick($file_handle);
$imagick->readImage();
$imagick->writeImages($yourImagename.'.jpg', false);
This will work for pdf having multiple pages as well as the single page.
$pdf_file = 'path/to/pdf/file.php';
$image = new imagick();
$image->setResolution(300,300);
$image->readImage($pdf);
$image->setImageFormat('jpg');
// Set all other properties
$pages = $image->getNumberImages();
if ($pages) {
foreach($image as $index => $pdf_image) {
$pdf_image->writeImage('destination/path/' . $index . '-image_file.jpg');
}
} else {
echo 'PDF doesn\'t have any pages';
}
Try something like this if you know number of pages of your pdf:
$images = new Imagick();
foreach ($pages as $p){
$im->readImage($PdfFile."[".$p."]"); //yourfile.pdf[0], yourfile.pdf[1], ...
$im->setCompression(Imagick::COMPRESSION_JPEG);
$im->setCompressionQuality(82);
$im->setImageFormat( "jpg" );
//...
$image_out = "image_".$p.".jpg";
$im->writeImage($image_out);
}
$im->clear();
$im->destroy();
If you dont know number of pages, you could do something like this:
$images = new Imagick();
$im->readImage($PdfFile);
$pages = (int)$im->getNumberImages();
this worked for me
$file = "./path/to/file/name.pdf";
$fileOpened = #fopen($archivo, 'rb');
$images = new Imagick();
$images->readImageFile($fileOpened);
foreach ($images as $i => $image) {
$image->setResolution(300, 300);
$image->setImageFormat("jpg");
$image->setImageCompression(imagick::COMPRESSION_JPEG);
$image->setImageCompressionQuality(90);
$image->setImageUnits(imagick::RESOLUTION_PIXELSPERINCH);
$data_blob = $image->getImageBlob();
$ouput="./path/images/files/page" . $i . ".jpg";
file_put_contents($ouput, $data_blob);
}
#fclose($fileOpened);
I hope I can help you too

displaying images from different sources

I am trying to generate an image report for a particular items. Every item has a unique item number, which is stored in the variable $pk.
In this, calling up images/$pk.jpg and/or screenshots/$pk.jpg will show the relevant image or screenshot for the current item page. This works fine in the actual page, however not in my popup report.
For one file, I wish to trim it to 800px before outputting, without storing the resultant file.
Additionally, people can upload files, so I am trying to retrieve a list of all files uploaded that end in png, and output each of these to the browser.
Below is my code, however only the html header is output.
What am I doing wrong? Is it a misuse of the imagepng method?
my code:
<?php
if (isset($_GET["pk"])) {
$pk = $_GET["pk"];
}
$con = mysqli_connect("localhost","user","pass", "db");
if (!$con) {
echo "Can't connect to MySQL Server. Errorcode: %s\n". mysqli_connect_error();
exit;
} {
echo "<h1>Image report for auction number: ".$pk. "</h1> \n";
$srcName = 'screenshots/'.$pk.'.png';
$info = getimageinfo($srcName);
$src = imagecreatefrompng($srcName);
$dest = imagecreate($info[0], min($info[1], 800));
imagecopy($dest, $src, 0, 0, 0, 0, $info[0], min($info[1], 800));
imagepng($dest);
imagepng('images/'.$pk.'.png');
$filesQuery = "SELECT FILENAME FROM FILES WHERE FILENAME LIKE %png%";
if ($getFiles = $con->prepare($filesQuery)) {
$getFiles->execute();
$getFiles->bind_result($FILENAME);
$files = array();
while ($getFiles->fetch()) {
$filename = array(
'FILENAME' => $FILENAME,
);
$files[] = $filename;
}
}
$filesList = '';
foreach ($files as $filenames) {
$imagepng($filenames['FILENAME']);
}
;
}
You cannot mix HTML and PNG output (that is: embed a PNG inside the HTML) as you are trying to do. You need to split this script in two parts.
The first part (e.g. report.php) outputs a list of all the images along with img tags. E.g:
<img src="/thumbnail.php?pk=1234567" />
Then you implement thumbnail.php to output the image (and just the image) along with the appropriate header. E.g:
<?php
$srcName = 'screenshots/'.$_GET['pk'].'.png';
$info = getimageinfo($srcName);
$src = imagecreatefrompng($srcName);
$dest = imagecreate($info[0], min($info[1], 800));
imagecopy($dest, $src, 0, 0, 0, 0, $info[0], min($info[1], 800));
header('Content-type: image/png');
imagepng($dest);
imagedestroy($src);
imagedestroy($dest);
?>
Two remarks on your code:
imagepng() takes an image resource as it's first parameter (a resource, as created with imagecreatefrompng or imagecreate). It does not take a filename as it's first parameter.
Always destroy the images you created with imagedestroy() or you will run out of memory over time (requiring a restart of your webserver).

Categories