imagemagick skew or distort an image - php

Well how could I change the before image to the after image by using imagemagick?
Is it the -skew command or the -distort, and how can I use it preferably in typo3 and php?
Any help is appreciated!

Using Imagemagick with php and the command line:
// Working on the original image size of 400 x 300
$cmd = "before.jpg -matte -virtual-pixel transparent".
" +distort Perspective \"0,0 0,0 400,0 400,22 400,300 400,320 0,300 0,300 \" ";
exec("convert $cmd perspective.png");
Note:
1/ This is for later versions of Imagemagick - the perspective operator has change.
2/ You need to use +distort not -distort as the image is larger than the initial image boundrys.
Examples of Imagemagick with php usage on my site http://www.rubblewebs.co.uk/imagemagick/operator.php

I think what you're looking for is the Imagick::shearImage function. This creates a checkerboard square and distorts it into a parallelogram (save this as a PHP file and open in your browser to see):
<?php
$im = new Imagick();
$im->newPseudoImage(300, 300, "pattern:checkerboard");
$im->setImageFormat('png');
$im->shearImage("transparent", 0, 10);
header("Content-Type: image/png");
echo $im;
?>
Within a larger script, to shear an image named myimg.png and save it as myimg-sheared.png, you can use:
$im = new Imagick("myimg.png");
$im->shearImage("transparent", 0, 10);
$im->writeImage("myimg_sheared.png");
If shearImage isn't versatile enough, you can try the Imagick::DISTORTION_PERSPECTIVE method via the Imagick::distortImage function.

Perspective distortion should give you what you want. Example:
convert original.png -matte -virtual-pixel white +distort Perspective '0,0,0,0 0,100,0,100 100,100,90,110 100,0,90,5' distorted.png
In TYPO3 you could apply it by (ab)using the SCALE object of the GIFBUILDER. Example:
temp.example = IMAGE
temp.example {
file = GIFBUILDER
file {
format = jpg
quality = 100
maxWidth = 9999
maxHeight = 9999
XY = [10.w],[10.h]
10 = IMAGE
10.file = fileadmin/original.png
20 = SCALE
20 {
params = -matte -virtual-pixel white +distort Perspective '0,0,0,0 0,100,0,100 100,100,90,110 100,0,90,5'
}
}
}

Related

padding images using php imagick

I need to create square images with no image loss. I found a tool that does the job as a bash script using ImageMagick but can never seem to be able to do it with php Imagick.
The script I found is called squareup from http://www.fmwconcepts.com/imagemagick/squareup/index.php
My code looks like this currently:
$image = new Imagick($srcimage);
$image->setCompressionQuality(100);
if ($image->getImageHeight() <= $image->getImageWidth())
$image->resizeImage($maxsize, 0, Imagick::FILTER_MITCHELL, 1);
else
$image->resizeImage(0, $maxsize, Imagick::FILTER_MITCHELL, 1);
$h=$image->getImageHeight();
$w=$image->getimagewidth();
$hlarge=0;
$wlarge=0;
if ($w>$h) {
$diff=intval(($w-$h)/2);
$wlarge=1;
$h=$w;
} else {
$diff=intval(($h-$w)/2);
$w=$h;
$hlarge=1;
}
$newimage = new Imagick();
if ($image->getImageColorspace() == Imagick::COLORSPACE_CMYK) {
$fg="cmyk(0,0,0,0)";
$fg_pixel=new ImagickPixel($fg);
$newimage->newImage($w, $h, $fg_pixel);
$newimage->setImageColorspace(Imagick::COLORSPACE_CMYK);
} else {
$newimage->newImage($w, $h, new ImagickPixel('#ffffff'));
}
$newimage->compositeImage($image,\Imagick::COMPOSITE_OVER,0,0);
$newimage->setImageCompression(Imagick::COMPRESSION_JPEG);
$newimage->setImageCompressionQuality(100);
$newimage->stripImage();
$newimage->writeImage($contactimage);
$newimage->destroy();
$image->destroy();
The simplest way to do pad to square or crop to square in ImageMagick 6 is as follows:
Input:
size=`convert hatching_orig.jpg -format "%[fx:max(w,h)]" info:`
convert hatching_orig.jpg -background red -gravity center -extent ${size}x${size} hatching_pad.jpg
size=`convert hatching_orig.jpg -format "%[fx:min(w,h)]" info:`
convert hatching_orig.jpg -background red -gravity center -extent ${size}x${size} hatching_crop.jpg
Same command, but different size variable.
In IM 7, you can do each in one command line.
These commands should be easy to convert to Imagick, I would expect. But should be done in sRGB colorspace. See http://us3.php.net/manual/en/imagick.extentimage.php

ImageMagick Trim Whitespace with offset

I am Trimming whitespace from my images using ImageMagick. Everything is working great and successfully trimming. But now I want to leave an offset of about 30px and cut extra whitespace from images. I mean to say my current result is
Now you can see that above image is completely trimmed but I want some offset like
I want to leave 30px on every side and trimming remaining whitespace. I am trimming with Fuzz with following code
$image = new Imagick('capfile.jpg');
$image->trimImage(25000);
I don't want to add borders or crop. I just want to trim with offset of 30px to main image itself because many of my images also have some light background colors which is trimmed using Fuzz so adding borders is not an option.
You can get the trim-box that ImageMagick would trim to like this at the command line:
convert -fuzz 10% -format %# cap.jpg info:
259x171+19+21
Then you can modify the width/height and offset as you wish before using the modified numbers to do a crop - i.e. subtract 30 from the x and y offset and add 60 to the width and height.
Edited by emcconville
How can I do this in php?
Here's a PHP alternative...
$img = new Imagick('/tmp/Zpuq9.jpg');
// Get Quantum to calculate 40%
$quantumInfo = $img->getQuantumRange();
// -fuzz 40%
$img->trimImage($quantumInfo['quantumRangeLong'] * 0.4);
// -format %#
$img->setOption('format','%#');
// info:
$img->setImageFilename('info:');
/*
* For this example, let's use PHP memory protocol
* to capture std out (from `info:').
*/
$fd = fopen('php://memory','rwb');
$img->writeImageFile($fd);
fseek($fd, 0);
$info = fread($fd, 1024);
fclose($fd);
var_dump($info);
//=> string(13) "258x170+19+22"
I know this kinda of silly but this worked for me and it is workaround. I couldn't get this so I figured out completely different approach.
1) Sometimes we are uploading photos that are visualisations like bedroom interior so we don't need to trim whitespace in photo because it is not existing. That is why we need to check if photo is bright or dark with get_avg_luminance function found in this thread https://stackoverflow.com/a/5959461/2760717
2) Now we have to write this
$src_image = new Imagick($src_file);
$dimmensions = $src_image->getImageGeometry();
$height = $dimmensions['height'];
$luminance = get_avg_luminance($src_file);
// If image is mostly bright then add white border with 5% of entire height
if ($luminance > 170) {
$quantumInfo = $src_image->getQuantumRange();
if ($src_image->trimImage($quantumInfo['quantumRangeLong']*0.1)) {
// add white border with 5% of offset
$src_image->borderImage('#ffffff', 0, ($height *0.05));
}
}
It is adding border to image and work ok for me :)

convert all pdf pages into image

In php using Imagick, I'm able to convert one pdf page into a jpg image at once. But I need to convert all pages of my pdf into jpg files in separate folder.
below my code
<?php
for($i=0;$i<=20;$i++){
$pdf_file = 'book.pdf';
$save_to = 'pages/tw'.$i.'.jpg';
$img = new imagick();
$img->setResolution(200,200);
$img->readImage("{$pdf_file}[$i]");
$img->scaleImage(800,0);
$img->setImageFormat('jpg');
$img = $img->flattenImages();
$img->writeImages($save_to, false);
$img->destroy();
}
?>
Above code produces results up-to 10 pages. Then it terminated by execution time of 30 secs. I cant manage php.ini because I'm using hosting with another company.
$mypdf = escapeshellarg( "mysafepdf.pdf" );
$newjpg = escapeshellarg( "output.jpg" );
$result = 0;
exec("convert -density 600 {$mypdf} {$newjpg} -colorspace RGB -resample 300", null, $result);
$ result will be 0 if the conversion works
-density = dpi
I hope this will help you!
PS.: This is only for one image, but you can adapt at it for your $i.

Filters for imagick using exec()

I have been working on converting PDFs to JPGs, for this I have installed imagick and GhostScript. I have been using exec() in my php code to make the conversion. Now my problem is that if the source of the input pdf is a conversion from doc->pdf, then the image quality is grainy when zoomed. On the other hand I need to keep the image size below 500kb, so I cannot use
density more than 200.
Is there a way to add any sort of filter before saving the images, so that the jpg quality is improved.
Here is my sample code:
$inputFileName = 'test.pdf';
$outputFileName = 'converted.jpg';
$sourceFile = escapeshellarg( $inputFileName );
$outputFile = escapeshellarg( $outputFileName );
$exe = "convert -density 200 -colorspace RGB {$sourceFile } {$outputFile }";
$null = "0";
echo exec( $exe, $null, $result );
Any help would be appreciated!
Thanks
Why not increasing the density and decreasing the quality? For example:
$exe = "convert -density 600 -quality 70 -colorspace RGB {$sourceFile } {$outputFile }";

Quickly get brightness / luminosity of images

I'm working in php, and going through each image pixel-by-pixel to get an average brightness for each image is going to be way to cpu intensive...
I've looked through both GD and imagemagick docs, but haven't found a way to return the average brightness of an image... Can this be done quickly either in these libraries, or in another package easily accessible by php?
Here is an interesting post using ImageMagick for computing the average graylevel of an image. This post also discusses Mark Ransom's technique of size reduction to 1x1 using ImageMagick.
In Imagemagick command line, you can convert to HSI or LAB and get the brightness (Intensity or Luminosity) from the average of the I or L channel. Any of these methods should work. Note that -scale 1x1 does a simple average of the whole image/channel and saves that value in 1 pixel result. -scale is very fast. It is not like -resize, which uses a specific filter function. Alternately, you can just compute the mean of the image without writing to 1 pixel.
convert image -colorspace HSI -channel b -separate +channel -scale 1x1 -format "%[fx:100*u]\n" info:
convert image -colorspace LAB -channel r -separate +channel -scale 1x1 -format "%[fx:100*u]\n" info:
convert image -colorspace HSI -channel b -separate +channel -format "%[fx:100*u.mean]\n" info:
convert image -colorspace LAB -channel r -separate +channel -format "%[fx:100*u.mean]\n" info:
convert image -colorspace HSI -channel b -separate +channel -format "%[mean]\n" info:
convert image -colorspace LAB -channel r -separate +channel -format "%[mean]\n" info:
The result will be between 0 and 100% with 0 being black and 100 white for all but the last two, where fx range is between 0 and 1. Thus the 100 factor to get percent. For the last two commands, the values will be between 0-255 for Q8 install and 0-65535 for Q16 install.
Note that channels are labeled in order as if they were r,g,b. But for modern versions of Imagemagick, you can use 0,1,2.
Alternately, you can get the pixel color for the channel which will be some gray value:
convert image -colorspace HSI -channel b -separate +channel -scale 1x1 -format "%[pixel:u.p{0,0}]\n" info:
convert image -colorspace LAB -channel r -separate +channel -scale 1x1 -format "%[pixel:u.p{0,0}]\n" info:
Sorry I do not know Imagick, but see
http://us3.php.net/manual/en/imagick.scaleimage.php
http://us3.php.net/manual/en/imagick.getimagepixelcolor.php
http://us3.php.net/manual/en/imagick.transformimagecolorspace.php
http://us3.php.net/manual/en/imagick.getimagechannelstatistics.php
or possibly
http://us3.php.net/manual/en/imagick.getimageproperty.php
Perhaps an Imagick expert would be kind enough to convert one of these commands from command line to Imagick code.
Sample? Just pick 10% of random pixels instead of 100%... Error rate will rise obviously but 10% of the pixels seems fine to me, in most cases it should yield great results!
Cache the values if using them more then once, because this is not a fast solution. I tried first to resize the image to 1x1 pixel with imagick, but the results were not good. Best results I got without imagick resize, but its very slow with big images. The example resizes to 1000x1000 pixels. Keep in mind this example does not cover images with alpha channel.
function getImageBrightness( $path )
{
$width = 1000;
$height = 1000;
try
{
$imagick = new imagick( $path );
$imagick->resizeImage( $width, $height );
$_brightness = 0;
for( $i=0; $i < $width; $i++ )
for( $j=0; $j < $height; $j++ )
if( $pixel = $imagick->getImagePixelColor($i, $j) )
if( $colors = $pixel->getColor() AND isset($colors['r']) )
{
$brightness = ($colors['r'] + $colors['g'] + $colors['b']) / (3* 255);
$_brightness = $brightness + $_brightness;
}
$_brightness = $_brightness / ( $height * $width );
return $_brightness; // from 0 (black) to 1 (white)
} catch( ImagickException $e )
{}
return 0.5; // default
}
Imagick has a histogram feature to return colors by count. You can more quickly average the same information without processing pixel-by-pixel.
Performance will be dependent on the number of colors in the image/histogram (e.g. a single color image will be extremely fast).
<?php
$image = new Imagick('image.jpg');
$pixels = $image->getImageHistogram(); // Generate histogram of colors
$sumbright = 0; // sum of brightness values
$cntbright = 0; // count of pixels
foreach($pixels as $p){
$color = $p->getColor(); // Get rbg pixel color
$cnt = $p->getColorCount(); // Get number of pixels with above color
$sumbright += (($color['r'] + $color['g'] + $color['b']) / (3*255)) * $cnt; // Calculate 0.0 - 1.0 value of brightness (0=rgb[0] 1=rgb[255])
$cntbright += $cnt;
}
$avgbright = $sumbright / $cntbright; // Average 0-1 brightness of all pixels in the histogram
?>

Categories