I'm using Imagick to generate JPG thumbnails for PDFs files but some of them generate with black areas (http://i.imgur.com/fKBncKw.jpg) – I'm assuming it's caused by transparency in the PDFs but can anything be done about it?
Code I'm using to generate these:
$imagick = new Imagick($filename);
$imagick->setIteratorIndex(0);
$imagick->setImageFormat('jpg');
return $imagick->getImageBlob();
Is there a way to flatten the PDF and/or add a white background so that the black areas don't appear?
Here is a solution which will only work for PNG to JPG.
This code adds a white background to the transparent areas in PNG and converts it to JPG.
What it does?
This code takes all PNG images from a folder, converts them to JPG's with white backgrounds and saves them in another folder.
<?php
ini_set('max_execution_time', 3000);
$dir = 'transparent/';
$arr = scandir($dir);
for($i=0;$i<count($arr);$i++)
{
if($i==0 || $i==1)
{
}
else{
$input_file = "transparent/".$arr[$i];
$output_file = "White/".str_replace('.png','.jpg',$arr[$i]);
$input = imagecreatefrompng($input_file);
list($width, $height) = getimagesize($input_file);
$output = imagecreatetruecolor($width, $height);
$white = imagecolorallocate($output, 255, 255, 255);
imagefilledrectangle($output, 0, 0, $width, $height, $white);
imagecopy($output, $input, 0, 0, 0, 0, $width, $height);
imagejpeg($output, $output_file);
}
}
?>
Its Image Processing and GD in PHP.
PHP Manual
Hope it helps, you can change it as you want.
Try this code: Imagick::setCompressionQuality
$im = new imagick(realpath($file).'[0]');
$im->setCompression(Imagick::COMPRESSION_JPEG);
$im->setCompressionQuality(100);
$im->setImageFormat("jpeg");
$im->writeImage("imagename.jpg");
Alternative solution: this may help:
<?php
//Note that the function returns an Imagick object and does not modify the existing object. Below is my code for converting a PNG with transparency into a JPG with a background color. This code illustrates the difference.
$im = new Imagick($filename);
$im->setImageBackgroundColor('white');
$im->flattenImages(); // This does not do anything.
$im = $im->flattenImages(); // Use this instead.
$im->setImageFormat('jpg');
$im->writeImage('image.jpg');
?>
use like this
class ImageConvertorLib{
private $CI;
/**
* loading codeIgniter instance
*/
public function __construct(){
$this->CI =& get_instance();
}
public function pdfToJpg($param){
$filename = $param['filename'];
$image_name = $param['image_name'];
$path = $param['path'];
$db_path = $param['db_path'];
$im = new Imagick();
$im->setResolution(220,220);
$im->readimage($filename."[0]");
$im->setImageFormat('jpeg');
$im->setImageBackgroundColor('#ffffff');
$im->flattenImages();
$image_name = $image_name.".jpg";//"save_as_name.jpg";
$imageprops = $im->getImageGeometry();
/*if ($imageprops['width'] <= 175 && $imageprops['height'] <= 300) {
// don't upscale
} else {
$im->resizeImage(175,300, imagick::FILTER_LANCZOS, 0.9, true);
}*/
$im->writeImage($path.$image_name);
if($im){
$Img = array();
$Img['status'] = 1;
$Img['image'] = ($db_path.$image_name);
return $Img;
}
$im->clear();
$im->destroy();
}
}
After endless attempts to append a pdf file with a jpeg image without getting black areas, I found the solution: the function transformImageColorspace
Used in this order works perfectly:
$im = new Imagick();
$im->readImage("file.pdf");
$im->transformImageColorspace(Imagick::COLORSPACE_SRGB);
$im->setImageFormat('jpeg');
$im->writeImage('image.jpg');
Related
I'm using the following PHP function to resize big images to fit 500 px width:
<?php
function resizeImage($name) {
header('Content-type: image/jpeg');
$filename = "file.jpg";
$new_width = 500;
list($width, $height) = getimagesize($filename);
$new_height = (($height*$new_width)/$width);
$image_p = imagecreatetruecolor($new_width, $new_height);
$image = imagecreatefromjpeg($filename);
imagecopyresampled($image_p, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
imagejpeg($image_p, "file.jpg", 100);
}
?>
For some reason the colors on the resized image aren't exactly the same as before. They aren't as clear and strong as before. As you can see [picture removed] there's more red color and brilliance in the left (original) photo.
Why that? Is there something wrong with my script? Or is it a normal resizing effect?
This is the working code I have now:
<?php
// Call the function with: resizeImage("INSERT_YOUR_FILE_NAME_INCLUDING_SUFFIX_HERE");
function resizeImage($file_name) {
// File is located at: files/original/
$filename = "files/original/".$file_name;
// The width you want the converted image has
$new_width = 500;
// Calculate right height
list($width, $height) = getimagesize($filename);
$new_height = (($height*$new_width)/$width);
// Get image
$small = new Imagick($filename);
// Resize image, but only if original image is wider what the wanted 500 px
if($width > $new_width) {$small->resizeImage($new_width, $new_height, Imagick::FILTER_LANCZOS, 1);}
// Some code to correct the color profile
$version = $small->getVersion();
$profile = "sRGB_IEC61966-2-1_no_black_scaling.icc";
if((is_array($version) === true) && (array_key_exists("versionString", $version) === true)) {$version = preg_replace("~ImageMagick ([^-]*).*~", "$1", $version["versionString"]);if(is_file(sprintf("/usr/share/ImageMagick-%s/config/sRGB.icm", $version)) === true) {$profile = sprintf("/usr/share/ImageMagick-%s/config/sRGB.icm", $version);}}if(($srgb = file_get_contents($profile)) !== false){$small->profileImage("icc", $srgb);$small->setImageColorSpace(Imagick::COLORSPACE_SRGB);}
// Safe the image to: files/small/
$small->writeImage("files/small/".$file_name);
// Clear all resources associated to the Imagick object
$small->clear();
}
?>
Don't forget to either download the icc file from http://www.color.org/sRGB_IEC61966-2-1_no_black_scaling.icc and save it in the same directory as your resize file or change $profile = "sRGB_IEC61966-2-1_no_black_scaling.icc"; to $profile = "http://www.color.org/sRGB_IEC61966-2-1_no_black_scaling.icc";!
My image file size is 800x600 and I want to resize this 800x600 to 400x300 then save both images(800x600 and 400x300) in the database base64_encode format. I can save in database first image (800x600) but how to convert a second image (400x300) in base64_encode format and save in database? I don't want to use two input fields. I think one input field enough for that.
$image = ($_FILES["my_image"]["name"]);
$theme_image = ($_FILES["my_image"]["tmp_name"]);
$bin_string = file_get_contents("$theme_image");
$theme_image_enc = base64_encode($bin_string);
You have to make a little script for create the new image from the first one and make the base64_encode on it
$WIDTH = 400; // The size of your new image
$HEIGHT = 300; // The size of your new image
$QUALITY = 100; //The quality of your new image
$DESTINATION_FOLDER = DependOfYourRepository; // The folder of your new image
// The directory where is your image
$filePath = DependOfYourRepository;
// This little part under depend if you wanna keep the ratio of the image or not
list($width_orig, $height_orig) = getimagesize($filePath);
$ratio_orig = $width_orig/$height_orig;
if ($WIDTH/$HEIGHT > $ratio_orig) {
$WIDTH = $HEIGHT*$ratio_orig;
} else {
$HEIGHT = $WIDTH/$ratio_orig;
}
// The function using are different for png, so it's better to check
if ($file_ext == "png") {
$image = imagecreatefrompng($filePath);
} else {
$image = imagecreatefromjpeg($filePath);
}
// I create the new image with the new dimension and maybe the new quality
$bg = imagecreatetruecolor($WIDTH, $HEIGHT);
imagefill($bg, 0, 0, imagecolorallocate($bg, 255, 255, 255));
imagealphablending($bg, TRUE);
imagecopyresampled($bg, $image, 0, 0, 0, 0, $WIDTH, $HEIGHT, $width_orig, $height_orig);
imagedestroy($image);
imagejpeg($bg, $DESTINATION_FOLDER.$filename, $QUALITY);
$bin_string_little = file_get_contents($DESTINATION_FOLDER.$filename);
// I remove the image created because you just wanna save the base64 version
unlike($DESTINATION_FOLDER.$filename);
imagedestroy($bg);
$theme_image_enc_little = base64_encode($bin_string_little);
// And now do what you want with the result
EDIT 1
It's possible to do it without using a directory for the second image but it's quite tricky.
$theme_image_little = imagecreatefromstring(base64_decode($theme_image_enc));
$image_little = imagecreatetruecolor($WIDTH, $HEIGHT);
// $org_w and org_h depends of your image, in your case, i guess 800 and 600
imagecopyresampled($image_little, $theme_image_little, 0, 0, 0, 0, $WIDTH, $HEIGHT, $org_w, $org_h);
// Thanks to Michael Robinson
// start buffering
ob_start();
imagepng($image_little);
$contents = ob_get_contents();
ob_end_clean();
$theme_image_enc_little = base64_encode($contents):
i have the following script for coping a JPEG and a PNG to an existing PNG called base.png. Within the function "transparent_background" i replace the white background with transparency. This function is the problem. Standlone the function is working with output directly in the browser. please see the comment out "//imagepng($img);". but if i return the $img out of the function its still a jpeg i think, thats why it isnt transparent. The second function is just for resize.
<?php
function transparent_background($img)
{
$img = imagecreatefromjpeg($img); //or whatever loading function you need
$colors= array("255","255","255");
$remove = imagecolorallocate($img, $colors[0], $colors[1], $colors[2]);
imagecolortransparent($img, $remove);
//imagepng($img);
return $img;
imagedestroy($img);
}
function resize($img, $w){
$img = imagecreatefromjpeg($img);
$ratio = imagesx($img)/imagesy($img);
if( $ratio > 1) {
$width = $w;
$height = $w/$ratio;
}
else {
$width = $w*$ratio;
$height = $w;
}
$dst = imagecreatetruecolor($width,$height);
imagecopyresampled($dst,$img,0,0,0,0,$width,$height,imagesx($img),imagesy($img));
return $dst;
imagedestroy($dst);
imagedestroy($img);
}
$h="https://images-eu.ssl-images-amazon.com/images/I/415zYwg2-TL.jpg";
$base = imagecreatefrompng("base.png");
$logo = imagecreatefrompng("fs_logo_line.png");
$pos1=resize($h,"730");
$pos1=transparent_background($h);
imagecopy($base,$pos1,0, 5, 0, 0, imagesx($pos1),imagesy($pos1));
imagecopy($base,$logo,0, 1136, 0,0,imagesx($logo),imagesy($logo));
imagepng($base);
?>
I think the problem is, that i get a jpeg back from the transparent_background function and thats why the image in $pos1 is not transparent. Any ideas how i can solve that? I have tried with ob_start & ob_get_contents but this also didn't work.
You can merge the two images together using the PHP GD2 library.
Example:
<?php
# If you don't know the type of image you are using as your originals.
$image = imagecreatefromstring(file_get_contents($your_original_image));
$frame = imagecreatefromstring(file_get_contents($your_frame_image));
# If you know your originals are of type PNG.
$image = imagecreatefrompng($your_original_image);
$frame = imagecreatefrompng($your_frame_image);
imagecopymerge($image, $frame, 0, 0, 0, 0, 50, 50, 100);
# Save the image to a file
imagepng($image, '/path/to/save/image.png');
# Output straight to the browser.
imagepng($image);
?>
Add imagealphablending($frame,true); before imagecopymerge() if you want to keep PNG frame transparancy over the image.
I have a function that generates text that fits the lower part of a circle. Because I do not know any other way that I can make the function fit the upper part of the circle so that it faces me, I want to rotate the image, write on it, rotate it back and again write on it. How can I do that without changing the name of the image?
I have tried something like this :
<?php
function create_image()
{
$im = #imagecreate(140, 140)or die("Cannot Initialize new GD image stream");
$background_color = imagecolorallocate($im, 255, 255, 255);
imageellipse ( $im , $cx , $cy , $size*2 , $size*2 , $black );
write($im,$cx,$cy,$size,$s,$e,$black,$text1,$font,$size,$pad);
imagerotate($im, 180,0);
write($im,$cx,$cy,$size,$s,$e,$black,$text2,$font,$size,$pad);
imagerotate($im, 180,0);
imagepng($im,"image.png");
imagedestroy($im);
}
?>
<?php
create_image();
print "<img src=image.png?".date("U").">";
?>
But it doesn't work. It doesn't rotate the image.
Can you please help me?
Thanx !
Why dont you just take the normal image and add some css to it
CSS
.yourImage {
-webkit-transform: rotate(-90deg);
-moz-transform: rotate(-90deg);
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3);
}
HTML
<img class="yourImage" src="originalImage.jpg">
Not sure why you need to rotate twice .. but this is what your code should look like
function create_image($img) {
$im = #imagecreatefrompng($img) or die("Cannot Initialize new GD image stream");
$rotate = imagerotate($im, 180, 0);
imagepng($rotate);
imagedestroy($rotate);
imagedestroy($im);
}
header('Content-Type: image/png');
$image = "a.png";
create_image($image);
You can do it easily using php rotate function. Here is simple code
<?php
$image = 'test.jpg';
// The file you are rotating
//How many degrees you wish to rotate
$degrees = 180;
// This sets the image type to .jpg but can be changed to png or gif
header('Content-type: image/jpeg') ;
// Create the canvas
$src = $image;
$system = explode(".", $src);
if (preg_match("/jpg|jpeg/", $system[1]))
{
$src_img=imagecreatefromjpeg($src);
}
if (preg_match("/png/", $system[1]))
{
$src_img = imagecreatefrompng($src);
}
if (preg_match("/gif/", $system[1]))
{
$src_img = imagecreatefromgif($src);
}
// Rotates the image
$rotate = imagerotate($src_img, $degrees, 0) ;
// Outputs a jpg image, you could change this to gif or png if needed
if (preg_match("/png/", $system[1]))
{
imagepng($rotate,$image);
}
else if (preg_match("/gif/", $system[1]))
{
imagegif($rotate, $image);
}
else
{
imagejpeg($rotate, $image);
}
imagedestroy($rotate);
imagedestroy($src_img);
?>
I have a quick question that I'm not quite sure to set up. I've seen examples elsewhere but nothing specifically like my situation. I would like to resize images using PHP so they're readable and not just wonkily stretched like if you use HTML. If they're not 250 pixels wide, or 160 pixels tall, how can I resize the picture so it's proportionate but fits within that space?
Thanks!
PHP does not manipulate images directly. You will need to use an image manipulation library such as gd or ImageMagick to accomplish this goal.
In ImageMagick, image resizing is accomplished like this:
$thumb = new Imagick('myimage.gif');
$thumb->resizeImage(320,240,Imagick::FILTER_LANCZOS,1);
$thumb->writeImage('mythumb.gif');
With GD, you can do it like this:
<?php
// The file
$filename = 'test.jpg';
$percent = 0.5;
// Content type
header('Content-Type: image/jpeg');
// Get new dimensions
list($width, $height) = getimagesize($filename);
$new_width = $width * $percent;
$new_height = $height * $percent;
// Resample
$image_p = imagecreatetruecolor($new_width, $new_height);
$image = imagecreatefromjpeg($filename);
imagecopyresampled($image_p, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
// Output
imagejpeg($image_p, null, 100);
?>
Ok, so below is an Image object that I use in my store. It maintains scale - requires GD
<?php
class Store_Model_Image extends My_Model_Abstract
{
const PATH = STORE_MODEL_IMAGE_PATH;
const URL = "/store-assets/product-images/";
public function get_image_url($width, $height)
{
$old_file = self::PATH . $this->get_filename();
$basename = pathinfo($old_file, PATHINFO_FILENAME);
$new_name = sprintf("%s_%sx%s.jpg", $basename, $width, $height);
if(file_exists(self::PATH . $new_name))
{
return self::URL . $new_name;
}
else
{
list($width_orig, $height_orig, $image_type) = #getimagesize($old_file);
$img = FALSE;
// Get the image and create a thumbnail
switch($image_type)
{
case 1:
$img = #imagecreatefromgif($old_file);
break;
case 2:
$img = #imagecreatefromjpeg($old_file);
break;
case 3:
$img = #imagecreatefrompng($old_file);
break;
}
if(!$img)
{
throw new Zend_Exception("ERROR: Could not create image handle from path.");
}
// Build the thumbnail
if($width_orig > $height_orig)
{
$width_ratio = $width / $width_orig;
$new_width = $width;
$new_height = $height_orig * $width_ratio;
}
else
{
$height_ratio = $height / $height_orig;
$new_width = $width_orig * $height_ratio;
$new_height = $height;
}
$new_img = #imagecreatetruecolor($new_width, $new_height);
// Fill the image black
if(!#imagefilledrectangle($new_img, 0, 0, $new_width, $new_height, 0))
{
throw new Zend_Exception("ERROR: Could not fill new image");
}
if(!#imagecopyresampled($new_img, $img, 0, 0, 0, 0, $new_width, $new_height, $width_orig, $height_orig))
{
throw new Zend_Exception("ERROR: Could not resize old image onto new bg.");
}
// Use a output buffering to load the image into a variable
ob_start();
imagejpeg($new_img, NULL, 100);
$image_contents = ob_get_contents();
ob_end_clean();
// lastly (for the example) we are writing the string to a file
$fh = fopen(self::PATH . $new_name, "a+");
fwrite($fh, $image_contents);
fclose($fh);
return self::URL . $new_name;
}
}
}
I resize the image at request time, so the first time the page loads an image will be resized to the required size for the template. (this means I don't have to crash a shared host trying to regenerate image thumbnails everytime my design changes)
So in the template you pass your image object, and when you need a image thumb,
<img src="<?php echo $image->get_image_url(100, 100); ?>" />
you now have a 100x100 thumb, which is saved to the Server for reuse at a later date
gd and imagemagick are two tools that may work for you
http://php.net/manual/en/book.image.php
http://php.net/manual/en/book.imagick.php
Here is something I used to use
class cropImage{
var $imgSrc,$myImage,$cropHeight,$cropWidth,$x,$y,$thumb;
function setImage($image,$moduleWidth,$moduleHeight,$cropPercent = "1") {
//Your Image
$this->imgSrc = $image;
//getting the image dimensions
list($width, $height) = getimagesize($this->imgSrc);
//create image from the jpeg
$this->myImage = imagecreatefromjpeg($this->imgSrc) or die("Error: Cannot find image!");
if($width > $height) $biggestSide = $width; //find biggest length
else $biggestSide = $height;
//The crop size will be half that of the largest side
//$cropPercent = 1.55; // This will zoom in to 50% zoom (crop)
if(!$cropPercent) {
$cropPercent = 1.50;
}
$this->cropWidth = $moduleWidth*$cropPercent;
$this->cropHeight = $moduleHeight*$cropPercent;
//$this->cropWidth = $biggestSide*$cropPercent;
//$this->cropHeight = $biggestSide*$cropPercent;
//getting the top left coordinate
$this->x = ($width-$this->cropWidth)/2;
$this->y = ($height-$this->cropHeight)/2;
}
function createThumb($moduleWidth,$moduleHeight){
$thumbSize = 495; // will create a 250 x 250 thumb
$this->thumb = imagecreatetruecolor($moduleWidth, $moduleHeight);
//$this->thumb = imagecreatetruecolor($thumbSize, $thumbSize);
imagecopyresampled($this->thumb, $this->myImage, 0, 0,$this->x, $this->y, $moduleWidth, $moduleHeight, $this->cropWidth, $this->cropHeight);
//imagecopyresampled($this->thumb, $this->myImage, 0, 0,$this->x, $this->y, $thumbSize, $thumbSize, $this->cropWidth, $this->cropHeight);
}
function renderImage(){
header('Content-type: image/jpeg');
imagejpeg($this->thumb);
imagedestroy($this->thumb);
}
}
Call it by using
$image = new cropImage;
$image->setImage($imagepath,$moduleWidth,$moduleHeight,$scaleRelation);
$image->createThumb($moduleWidth,$moduleHeight);
$image->renderImage();
Use GD or ImageMagick. Here you may find a real production example of code (used by MediaWiki) that supports consoled ImageMagick interface (transformImageMagick method), ImageMagick extension interface (transformImageMagickExt method) and GD (transformGd method).
There a simple to use, open source library called PHP Image Magician that will can help you out.
Example of basis usage:
$magicianObj = new imageLib('racecar.jpg');
$magicianObj -> resizeImage(100, 200, 'crop');
$magicianObj -> saveImage('racecar_small.png');