I have a problem with my php: when I make conversion PDF to JPG not shown correctly.
This is the original pictures of pdf - > http://s16.postimg.org/ma0jizgt1/text_problem2_fw.png
This is the jpg after converting with imagick - > http://s14.postimg.org/ilhs9tt3l/text_problem_fw.png
Please can you help me ?
Thank you
PHP:
if (move_uploaded_file( $_FILES["files"]["tmp_name"], $uploadUrlPdf . $_FILES["files"]["name"]))
{
$_FILES['files']['name'];
$nr_pag = $_POST['nr_pagini'];
for($i = 0; $i < $nr_pag; $i++)
{
$fn = $uploadUrlSwf.sprintf("%02d", "$i").".jpg";
if (!file_exists($fn))
{
$im = new imagick();
$im->setResolution($dpi,$dpi);
$pdf = $uploadUrlPdf.$_FILES['files']['name']."[$i]";
$im->readimage($pdf);
$im->setImageFormat('jpg');
$im->writeImage($fn);
file_put_contents( $fn, (string)$im );
$im->clear();
$im->destroy();
}
}
}
else
{
echo "error!";
}
Try setting your dpi value higher. If that does not work, try another export format (other than jpg). SVG would be your best bet, because you can scale that while the text and other shapes are still perfect quality. JPG wil not be sharp at a high zoom level if the resolution (dpi) is too low.
This forum entry might help: anti-aliased text when exporting PDF to image
Related
I'm having a problem when im trying to convert a PDF to images with imagick and PHP (5.5). everything works fine i can create a image for each page in the PDF but i run into the following problems. and have been stuck here for days now.
When i create a image from a PDF file some of them gets a black background even thou i have set setImageBackgroundColor to white
I have tried to set setImageCompressionQuality to get the image in better quality (right not the created image gets pixelated).
also i cannot seem to change the DPI version of the image to a 72 dpi one.
the code is as following:
$file_name = basename($file_name);
$img = new imagick();
$img->readImage($dir.'/'.$file_name);
$img->setImageBackgroundColor('white');
$img->setResolution(72,72);
$img->resampleImage(72,72,imagick::FILTER_LANCZOS,0);
$img->setImageUnits(imagick::RESOLUTION_PIXELSPERINCH);
$img->setImageCompression(imagick::COMPRESSION_JPEG);
$img->setImageCompressionQuality(100);
$img->stripImage();
$num_pages = $img->getNumberImages();
for($i = 0;$i < $num_pages; $i++) {
$img->setIteratorIndex($i);
$img->setImageBackgroundColor('white');
$img->flattenImages();
$img->setImageFormat("jpeg");
$final_name = str_replace(" ", "+", basename(str_replace(".".$file_ext,"", $file_name)));
$final_name = preg_replace("/[^a-zA-Z0-9-+]/", "", $final_name);
$save_to = $pdf_dir."/".str_replace(".".$file_ext,"", $final_name).'-'.$i.'.jpg';
$img->writeImage($save_to);
$file_image = str_replace(dirname(__FILE__)."/../../", "/", $save_to);
$file_images[] = $file_image;
}
$img->destroy();
You had some mistakes in your code.
setResolution needs to be called before loading the PDF
You need to use setBackgroundColor rather than setImageBackgroundColor.
You probably want to set the individual page compression quality, but see below.
So code:
$imagick = new Imagick();
$imagick->setResolution(72, 72);
$imagick->readImage($file_name);
$imagick->setBackgroundColor('white');
$imagick->setImageCompression(imagick::COMPRESSION_JPEG);
$imagick->setImageCompressionQuality(70);
foreach ($imagick as $c => $_page) {
$_page->setBackgroundColor('white');
$_page->setImageCompressionQuality(70);
$_page->setImageFormat('jpg');
$_page->writeImage($file."_background-$c.jpg");
}
btw, the fact that you're using JPEG at 100 quality is disturbing. If that is an image that is going to be sent to a browser, the quality should be lower than 100. If you are using it as an intermediate picture, using PNG as the intermediate format is better as it is lossless and it supports transparency.
That seemed to do the trick, changed to answer a bit as i couldnt get your foreach to work thou, wich made it work as intended:
Thank you for saving me from alot of headache.
$img = new imagick();
$img->setResolution(72, 72);
$img->readImage($dir.'/'.$file_name);
$img->setBackgroundColor('white');
$img->setImageCompression(imagick::COMPRESSION_JPEG);
$img->setImageCompressionQuality(70);
$num_pages = $img->getNumberImages();
for($i = 0;$i < $num_pages; $i++) {
$final_name = str_replace(" ", "+", basename(str_replace(".".$file_ext,"", $file_name)));
$final_name = preg_replace("/[^a-zA-Z0-9-+]/", "", $final_name);
$save_to = $pdf_dir."/".str_replace(".".$file_ext,"", $final_name).'-'.$i.'.jpg';
$img->setIteratorIndex($i);
$img->setBackgroundColor('white');
$img->setImageCompressionQuality(70);
$img->setImageFormat('jpg');
$img->writeImage($save_to);
$file_image = str_replace(dirname(__FILE__)."/../../", "/", $save_to);
$file_images[] = $file_image;
}
I tried to make a thumbnail of a pdf file which is hosted on another server. My current code is:
<?php
$im = new imagick("http://www.d3publisher.us/Walkthroughs/Naruto_NC_3_DS.pdf");
$im->setImageFormat('jpg');
header('Content-Type: image/jpeg');
echo $im;
?>
The problem is that code is only generating thumbnail for LAST PAGE of the pdf file. How can I make a thumbnail for first page only? I tried to add [0] at the imagick line.
$im = new imagick("http://www.d3publisher.us/Walkthroughs/Naruto_NC_3_DS.pdf[0]");
but it didn't work. It only work for local pdf file, i.e:
$im = new imagick("my-pdf-file.pdf[0]");
Please help me solve this problem.. Thanks..
You'll need to reset the active image to the first page. This can be done with Imagick::setIteratorIndex.
<?php
$im = new imagick("http://www.d3publisher.us/Walkthroughs/Naruto_NC_3_DS.pdf");
$im->setIteratorIndex(0);
$im->setImageFormat('jpg');
header('Content-Type: image/jpeg');
echo $im;
?>
Try...
$im->setImageIndex(0); //this will return 1th page of the pdf file
$im->setImageFormat('jpg');
"This can be done with Imagick::setIteratorIndex. .."
..or not. Simply has no effect . Setting it to one crashes something, setting it to 0 gets the last page..
function make_thumbnail($filename)
{
try
{
$imagick= new Imagick($filename);
}
catch(ImagickException $e)
{
// failed to make a thimbynail. what now?
// load up our trusty truetype font png instead?
$imagick->destroy();
return "0"; // shove any rubbish in the db - it will just say no image available when asked.
}
$imagick->setIteratorIndex(0);// rewind to first page or image of a multi series
$imagick->setImageFormat("png"); // turn it into a png
$imagick = $imagick->flattenImages(); // remove any transparency
$imagick->scaleImage(300,0); //resize...to less than 300px wide
$d = $imagick->getImageGeometry();
$h = $d['height'];
if($h > 300)
$imagick->scaleImage(0,300);
$imagick->setImageCompression(\Imagick::COMPRESSION_UNDEFINED);
$imagick->setImageCompressionQuality(0);
$imagick->setIteratorIndex(0);
$a = $imagick->getImageBlob(); // output as bytestream
$imagick->destroy();
return $a;
}
What I want to do is to save only the first frame of an animated GIF in static image (non animated gif).
Using Gmagick 1.1.2RC1 and GraphicMagick 3.1.18
I read heaps of posts talking about it. Some says that it was working in the previous version of Gmagick but not in the new one.
Here is my current test code:
public function testAnimatedGifFrame()
{
$testAnimGif = $this->assets.'/animated.gif';
$im = new \Gmagick($testAnimGif);
$frameNumber = $im->getNumberImages();
$this->assertEquals(47, $frameNumber, 'The number of frame for the animated GIF should be 47');
// Select the first frame and save it
$frameIndex = 0;
$img = $im->coalesceImages();
foreach ($img as $frame) {
die('here');
$frameName = ++$frameIndex . '.gif';
$frame->writeImage( $frameName );
}
}
The animated GIF is composed of 47 frames, but when using coalesceImages(), the script is never getting inside the foreach loop (it's never dying).
Not sure what I've missed here.
For those looking to do it using Imagick or Gmagick like I was.
Just save it as a JPG and BAM!
public function testAnimatedGifFrame()
{
$testAnimGif = $this->assets.'/animated.gif';
$singleFrame = $this->assets.'/test_single_frame.jpg';
$im = new \Gmagick($testAnimGif);
$frameNumber = $im->getNumberImages();
$this->assertEquals(47, $frameNumber, 'The number of frame for the animated GIF should be 47');
// Save the image as JPG to disable the animation
$im->setImageFormat('JPG');
$im->writeImage($singleFrame);
$im->destroy();
}
If you want to save the last image of the animation instead of the first one, you just need to add $im = $im->flattenImages(); before $im->setImageFormat('JPG');
I hope this will help some of you ;)
I am new to jQuery but im loving it! ive have a problem i cant get round as of yet.
I am using http://www.zurb.com/playground/ajax_upload
which i have got working using the following upload.php
<?
$time= time();
$uploaddir = 'users/'; //<-- Changed this to my directory for storing images
$uploadfile = $uploaddir.$time.basename($_FILES['userfile']['name']); //<-- IMPORTANT
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
echo $uploaddir.$time.$_FILES['userfile']['name']; // IMPORTANT
#print_r($_FILES);
} else {
// WARNING! DO NOT USE "FALSE" STRING AS A RESPONSE!
// Otherwise onSubmit event will not be fired
echo "error";
}
?>
i have added the time variable to ensure each image is unique. The problem i have is i want to resize and optimise the image on the fly and i am not sure how to do this.
The resize is the most important featuer i require - for example i would like a max width of 300px for the image that is saved even if it was originally 1000px wide. I need to resize proportionaly ( is that a word? :) )
Any help will be great.
Regards
M
To resize images you need libs like GD
The standard function to do this is GD's imagecopyresampled.
In the example is shown one way to resize and keeping the proportion:
//> MAx
$width = 200;
$height = 200;
// Get new dimensions
list($width_orig, $height_orig) = getimagesize($filename);
$ratio_orig = $width_orig/$height_orig;
if ($width/$height > $ratio_orig) {
$width = $height*$ratio_orig;
} else {
$height = $width/$ratio_orig;
}
There is two main image manipulation things in PHP, GD or Imagemagick. Both will be able to do what you need. You will need to configure them on your PHP webserver.
Is there any way to remove the EXIF data from a JPG using PHP? I have heard of PEL, but I'm hoping there's a simpler way. I am uploading images that will be displayed online and would like the EXIF data removed.
Thanks!
EDIT: I don't/can't install ImageMagick.
Use gd to recreate the graphical part of the image in a new one, that you save with another name.
See PHP gd
edit 2017
Use the new Imagick feature.
Open Image:
<?php
$incoming_file = '/Users/John/Desktop/file_loco.jpg';
$img = new Imagick(realpath($incoming_file));
Be sure to keep any ICC profile in the image
$profiles = $img->getImageProfiles("icc", true);
then strip image, and put the profile back if any
$img->stripImage();
if(!empty($profiles)) {
$img->profileImage("icc", $profiles['icc']);
}
Comes from this PHP page, see comment from Max Eremin down the page.
A fast way to do it in PHP using ImageMagick (Assuming you have it installed and enabled).
<?php
$images = glob('*.jpg');
foreach($images as $image)
{
try
{
$img = new Imagick($image);
$img->stripImage();
$img->writeImage($image);
$img->clear();
$img->destroy();
echo "Removed EXIF data from $image. \n";
} catch(Exception $e) {
echo 'Exception caught: ', $e->getMessage(), "\n";
}
}
?>
I was looking for a solution to this as well. In the end I used PHP to rewrite the JPEG with ALL Exif data removed. I didn't need any of it for my purposes.
This option has several advantages...
The file is smaller because the EXIF data is gone.
There is no loss of image quality (because the image data is unchanged).
Also a note on using imagecreatefromjpeg: I tried this and my files got bigger. If you set quality to 100, your file will be LARGER, because the image has been resampled, and then stored in a lossless way. And if you don't use quality 100, you lose image quality. The ONLY way to avoid resampling is to not use imagecreatefromjpeg.
Here is my function...
/**
* Remove EXIF from a JPEG file.
* #param string $old Path to original jpeg file (input).
* #param string $new Path to new jpeg file (output).
*/
function removeExif($old, $new)
{
// Open the input file for binary reading
$f1 = fopen($old, 'rb');
// Open the output file for binary writing
$f2 = fopen($new, 'wb');
// Find EXIF marker
while (($s = fread($f1, 2))) {
$word = unpack('ni', $s)['i'];
if ($word == 0xFFE1) {
// Read length (includes the word used for the length)
$s = fread($f1, 2);
$len = unpack('ni', $s)['i'];
// Skip the EXIF info
fread($f1, $len - 2);
break;
} else {
fwrite($f2, $s, 2);
}
}
// Write the rest of the file
while (($s = fread($f1, 4096))) {
fwrite($f2, $s, strlen($s));
}
fclose($f1);
fclose($f2);
}
The code is pretty simple. It opens the input file for reading and the output file for writing, and then starts reading the input file. It data from one to the other. Once it reaches the EXIF marker, it reads the length of the EXIF record and skips over that number of bytes. It then continues by reading and writing the remaining data.
The following will remove all EXIF data of a jpeg file. This will make a copy of original file without EXIF and remove the old file. Use 100 quality not to loose any quality details of picture.
$path = "/image.jpg";
$img = imagecreatefromjpeg ($path);
imagejpeg ($img, $path, 100);
imagedestroy ($img);
(simple approximation to the graph can be found here)
function remove_exif($in, $out)
{
$buffer_len = 4096;
$fd_in = fopen($in, 'rb');
$fd_out = fopen($out, 'wb');
while (($buffer = fread($fd_in, $buffer_len)))
{
// \xFF\xE1\xHH\xLLExif\x00\x00 - Exif
// \xFF\xE1\xHH\xLLhttp:// - XMP
// \xFF\xE2\xHH\xLLICC_PROFILE - ICC
// \xFF\xED\xHH\xLLPhotoshop - PH
while (preg_match('/\xFF[\xE1\xE2\xED\xEE](.)(.)(exif|photoshop|http:|icc_profile|adobe)/si', $buffer, $match, PREG_OFFSET_CAPTURE))
{
echo "found: '{$match[3][0]}' marker\n";
$len = ord($match[1][0]) * 256 + ord($match[2][0]);
echo "length: {$len} bytes\n";
echo "write: {$match[0][1]} bytes to output file\n";
fwrite($fd_out, substr($buffer, 0, $match[0][1]));
$filepos = $match[0][1] + 2 + $len - strlen($buffer);
fseek($fd_in, $filepos, SEEK_CUR);
echo "seek to: ".ftell($fd_in)."\n";
$buffer = fread($fd_in, $buffer_len);
}
echo "write: ".strlen($buffer)." bytes to output file\n";
fwrite($fd_out, $buffer, strlen($buffer));
}
fclose($fd_out);
fclose($fd_in);
}
It is a prototype for a call from a command line.
this is the simplest way:
$images = glob($location.'/*.jpg');
foreach($images as $image) {
$img = imagecreatefromjpeg($image);
imagejpeg($img,$image,100);
}
I completely misunderstood your question.
You could use some command line tool to do this job. or write your own php extension to do it. have a look at this lib that would be useful: http://www.sno.phy.queensu.ca/~phil/exiftool/
Cheers,
vfn
I'm not pretty sure about it, but if its possible using GD o ImageMagick, the first thing that come to my mind is to create a new Image and add the old image to the new one.