How can I calculate the variation of an image in Imagick? I already converted the image in greyscale, but through native functions I can only get Mean and Standard Deviation.
My approach is generating two noise images and calculate the Euclidian difference between both RGB pixel color values.
This will certainly look better with real images for example of a webcam.
$getRandomNoiseImage = function ($x, $y, $steps): Imagick {
$draw = new ImagickDraw();
$draw->setResolution($x, $y);
$draw->setStrokeWidth(1);
$pixel = new ImagickPixel();
for ($i = 0; $i < $x; $i += $steps) {
for ($j = 0; $j < $y; $j += $steps) {
$color = join(',', [rand(0, 255), rand(0, 255), rand(0, 255)]);
$pixel->setColor("rgb($color)");
$draw->setFillColor($pixel);
$draw->setStrokeColor($pixel);
$draw->rectangle($i, $j, $i + $steps, $j + $steps);
}
}
$im = new Imagick();
$im->newImage($x, $y, new ImagickPixel('black'));
$im->drawImage($draw);
return $im;
};
$width = 64;
$height = 64;
$im1 = $getRandomNoiseImage($width, $height, 16);
$im2 = $getRandomNoiseImage($width, $height, 16);
$draw = new ImagickDraw();
$draw->setResolution($width, $height);
$draw->setStrokeWidth(1);
$pixel = new ImagickPixel();
for ($i = 0; $i < $width; $i++) {
for ($j = 0; $j < $height; $j++) {
$c1 = $im1->getImagePixelColor($i, $j)->getColor(0);
$c2 = $im2->getImagePixelColor($i, $j)->getColor(0);
$color = [
sqrt(abs($c2['r']**2 - $c1['r']**2)),
sqrt(abs($c2['g']**2 - $c1['g']**2)),
sqrt(abs($c2['b']**2 - $c1['b']**2)),
];
$pixel->setColor(sprintf('rgb(%d,%d,%d)', ...$color));
$draw->setFillColor($pixel);
$draw->setStrokeColor($pixel);
$draw->rectangle($i, $j, $i + 1, $j + 1);
}
}
$im3 = new Imagick();
$im3->newImage($width, $height, new ImagickPixel('black'));
$im3->drawImage($draw);
$im1->writeImage('image1.png');
$im2->writeImage('image2.png');
$im3->writeImage('image3.png');
Related
I have a script that crops and rotates an image.
But i end up with a black bar in my image:
http://prntscr.com/r9l1w5 (screenshot)
I found a script on the internet, that is able to remove black bars on images. But i am unable to make it work together on 1 page.
(view-image.php) My script:
<?php
$filenamegetter = $_GET['imgid'];
$degree = 0;
// File and rotation
$filename = 'img/' . $filenamegetter . '';
$degrees = $degree;
$percent = 0.30;
// Content type
header('Content-type: image/jpeg');
// Get new sizes
list($width, $height) = getimagesize($filename);
if ($width > "1000") {
$newwidth = $width * $percent;
$newheight = $height * $percent;
} else {
$newwidth = $width;
$newheight = $height;
}
// Load
$thumb = imagecreatetruecolor($newwidth, $newheight);
$source = imagecreatefromjpeg($filename);
// Rotate
$rotate = imagerotate($source, $degrees, 0);
imagecopyresized($thumb, $rotate, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);
imagejpeg($thumb);
// Free the memory
imagedestroy($source);
imagedestroy($thumb);
?>
The anti black bar script i wish it works together with:
<?php
$image_path = "image.jpg";
$jpg = imagecreatefromjpeg($image_path);
$black = array("red" => 0, "green" => 0, "blue" => 0, "alpha" => 0);
$removeLeft = 0;
for($x = 0; $x < imagesx($jpg); $x++) {
for($y = 0; $y < imagesy($jpg); $y++) {
if(imagecolorsforindex($jpg, imagecolorat($jpg, $x, $y)) != $black){
break 2;
}
}
$removeLeft += 1;
}
$removeRight = 0;
for($x = imagesx($jpg)-1; $x > 0; $x--) {
for($y = 0; $y < imagesy($jpg); $y++) {
if(imagecolorsforindex($jpg, imagecolorat($jpg, $x, $y)) != $black){
break 2;
}
}
$removeRight += 1;
}
$removeTop = 0;
for($y = 0; $y < imagesy($jpg); $y++) {
for($x = 0; $x < imagesx($jpg); $x++) {
if(imagecolorsforindex($jpg, imagecolorat($jpg, $x, $y)) != $black){
break 2;
}
}
$removeTop += 1;
}
$removeBottom = 0;
for($y = imagesy($jpg)-1; $y > 0; $y--) {
for($x = 0; $x < imagesx($jpg); $x++) {
if(imagecolorsforindex($jpg, imagecolorat($jpg, $x, $y)) != $black){
break 2;
}
}
$removeBottom += 1;
}
$cropped = imagecreatetruecolor(imagesx($jpg) - ($removeLeft + $removeRight), imagesy($jpg) - ($removeTop + $removeBottom));
imagecopy($cropped, $jpg, 0, 0, $removeLeft, $removeTop, imagesx($cropped), imagesy($cropped));
header("Content-type: image/jpeg");
imagejpeg($cropped); //change to `imagejpeg($cropped, $image_path);` to save
imagedestroy($cropped);
imagedestroy($jpg);
I'd like to know how i can implent the anti black bar script in my script. I tried multiple ways but i end up with a empty page.
For anyone having problems with imagecopyresampled or imagerotate with black bars on background, I have found a code example here:
There are a lot of factors but for me the problem was the new size after rotating the image.
https://qna.habr.com/q/646622#answer_1417035
// get image sizes (X,Y)
$wx = imagesx($imageW);
$wy = imagesy($imageW);
// create a new image from the sizes on transparent canvas
$new = imagecreatetruecolor($wx, $wy);
$transparent = imagecolorallocatealpha($new, 0, 0, 0, 127);
$rotate = imagerotate($imageW, 280, $transparent);
imagealphablending($rotate, true);
imagesavealpha($rotate, true);
// get the newest image X and Y
$ix = imagesx($rotate);
$iy = imagesy($rotate);
//copy the image to the canvas
imagecopyresampled($destImg, $rotate, 940, 2050, 0, 0, $ix, $iy, $ix, $iy);
So, my problem is that i'm using FPDF to create a pdf file from php. Just one problem. Once text is too large for a cell it doesn't wrap. So i came to the point to try to use multicells, but there is another problem. Once a cell is wrapped in a table i got no way to get the other multicells to the same height.
Here is the code i tested.
<?php
require('../fpdf181/fpdf.php');
$pdf = new FPDF('P', 'mm', 'A4');
$pdf->AliasNbPages();
$pdf->AddPage();
$pdf->SetFont('Arial', '', 14);
$x = $pdf->GetX();
$y = $pdf->GetY();
$push_right = 0;
$pdf->MultiCell(50,10,"TEST shdfkjhdsafhahsjdkfkhjshakjfhdsdsfhkjdkjhsafhkjdakjhsfhkjdskjhaf", "TBRL");
$pdf->SetXY($x+50, $y);
$pdf->MultiCell(50,10,"TEST shdfkjhdsafhahsjdkfkhjshakjfhdsdsfhkjdsafsdafdsafsdafsdafddkjhsafhkjdakjhsfhkjdskjhaf", "TBRL");
$pdf->Output();
From that code i got this:
But it should look like this:
This is how it works, for those who have the same problem:
function MultiCellRow($cells, $width, $height, $data, $pdf)
{
$x = $pdf->GetX();
$y = $pdf->GetY();
$maxheight = 0;
for ($i = 0; $i < $cells; $i++) {
$pdf->MultiCell($width, $height, $data[$i]);
if ($pdf->GetY() - $y > $maxheight) $maxheight = $pdf->GetY() - $y;
$pdf->SetXY($x + ($width * ($i + 1)), $y);
}
for ($i = 0; $i < $cells + 1; $i++) {
$pdf->Line($x + $width * $i, $y, $x + $width * $i, $y + $maxheight);
}
$pdf->Line($x, $y, $x + $width * $cells, $y);
$pdf->Line($x, $y + $maxheight, $x + $width * $cells, $y + $maxheight);
}
To execute the function I used: MultiCellRow(3, 50, 10, ["Cell1","Cell2", "Cell3"], $pdf);
The accepted answer works for non-colored backgrounds. If, you wanted to have colored backgrounds, then the accepted answer wouldn't shade the smaller height columns properly.
The below code provides the same functionality as the approved answer, but also supports colored backgrounds. It may not be the cleanest solution (because it has to render the MultiCell components twice), but is the only solution I could create that actually works:
function MultiCellRow($pdf, $data, $width, $height,$darkenBackground){
$x = $pdf->GetX();
$y = $pdf->GetY();
$maxheight = 0;
for ($i = 0; $i < count($data); $i++) {
$pdf->MultiCell($width, $height, $data[$i],0,'C');
if ($pdf->GetY() - $y > $maxheight) $maxheight = $pdf->GetY() - $y;
$pdf->SetXY($x + ($width * ($i + 1)), $y);
}
for ($i = 0; $i < count($data); $i++) {
if($darkenBackground) $pdf->Rect($x+$width*$i,$y,$width,$maxheight,"F");
$pdf->Line($x + $width * $i, $y, $x + $width * $i, $y + $maxheight);
$pdf->SetXY($x+$i*$width,$y);
$pdf->MultiCell($width, $height, $data[$i],0,'C');
}
$pdf->Line($x + $width * count($data), $y, $x + $width * count($data), $y + $maxheight);
$pdf->Line($x, $y, $x + $width * count($data), $y);
$pdf->Line($x, $y + $maxheight, $x + $width * count($data), $y + $maxheight);
$pdf->SetY($y+$maxheight);}
Where the inputs are:
$pdf is the pdf object (new FPDF();)
$data is the array of strings to be rendered in the row
$width is the cell width (integer)
$height is determines the padding/line-spacing of the cell
$darkenBackground is a Boolean.
I give partial credit to "Florian7843" for the first half of the code. I would have edited their existing post, but I made significant changes and thought it would be better to contribute a separate answer.
If somebody wants to dedicate a cleaner/efficient solution, please propose an edit.
Cheers!
i'm trying to work a little bit with images and php. Please have a look at the following script.
<?php
//testcall prepare.php?img=https://images-eu.ssl-images-amazon.com/images/I/515SENGgRnL.jpg&h=200&n=test.png
$file=$_GET["img"];
$height=$_GET["h"];
$name=$_GET["n"];
function transparent($picture)
{
$img_w = imagesx($picture);
$img_h = imagesy($picture);
$newPicture = imagecreatetruecolor( $img_w, $img_h );
imagesavealpha( $newPicture, true );
$rgb = imagecolorallocatealpha( $newPicture, 0, 0, 0, 127 );
imagefill( $newPicture, 0, 0, $rgb );
$color = imagecolorat( $picture, $img_w-1, 1);
for( $x = 0; $x < $img_w; $x++ ) {
for( $y = 0; $y < $img_h; $y++ ) {
$c = imagecolorat( $picture, $x, $y );
if($color!=$c){
imagesetpixel( $newPicture, $x, $y, $c);
}
}
}
echo "habs transparent gemacht! <br> ";
return $newPicture;
}
function resize($img,$w,$name){
$ratio = imagesx($img)/imagesy($img);
if( $ratio > 1) {
$width = $w;
$height = $w/$ratio;
}
else {
$width = $w*$ratio;
$height = $w;
}
$dst = imagecreatetruecolor($width,$height);
imagesavealpha($dst, true);
$color = imagecolorallocatealpha($dst, 0, 0, 0, 127);
imagefill($dst, 0, 0, $color);
imagecopyresampled($dst,$img,0,0,0,0,$width,$height,imagesx($img),imagesy($img));
imagepng($dst, "test.png");
};
function crop($img){
$img = imagecreatefromjpeg($img);
$b_top = 0;
$b_btm = 0;
$b_lft = 0;
$b_rt = 0;
for(; $b_top < imagesy($img); ++$b_top) {
for($x = 0; $x < imagesx($img); ++$x) {
if(imagecolorat($img, $x, $b_top) != 0xFFFFFF) {
break 2;
}
}
}
for(; $b_btm < imagesy($img); ++$b_btm) {
for($x = 0; $x < imagesx($img); ++$x) {
if(imagecolorat($img, $x, imagesy($img) - $b_btm-1) != 0xFFFFFF) {
break 2;
}
}
}
for(; $b_lft < imagesx($img); ++$b_lft) {
for($y = 0; $y < imagesy($img); ++$y) {
if(imagecolorat($img, $b_lft, $y) != 0xFFFFFF) {
break 2;
}
}
}
for(; $b_rt < imagesx($img); ++$b_rt) {
for($y = 0; $y < imagesy($img); ++$y) {
if(imagecolorat($img, imagesx($img) - $b_rt-1, $y) != 0xFFFFFF) {
break 2;
}
}
}
$newimg = imagecreatetruecolor(imagesx($img)-($b_lft+$b_rt), imagesy($img)-($b_top+$b_btm));
imagecopy($newimg, $img, 0, 0, $b_lft, $b_top, imagesx($newimg), imagesy($newimg));
return $newimg;
};
$pic_cropped=crop($file);
$pic_transparent=transparent($pic_cropped);
$pic_resized=resize($pic_transparent,$height,$name);
?>
Input is a jpg, height and output name. First function crop crops the white space on all sides. Then set the white background color to transparent and the resize the whole pic to the height. So far the script is running fine on my Mac with MAMP. I tried to run on raspberry pi and on Ubuntu Linux in hosted area. The out on my mac is perfect: https://ibb.co/fNeFzk
Output on Raspberry and hosted Linux is bad: https://ibb.co/kdbCek
Hope you can see the difference. Same PHP Version, Same Apache Version. Any Ideas how to solve that?
So I want to be able to jumble up an image so as to distort the original image. What I mean is this. Load an image, loop through the image and take 32x32 blocks and store each individual block in an array. Then reassemble them as a new picture with the blocks in random order.
this is the code I have currently to take and store the blocks from original image and then create reassemble the image (Note this doesn't have the randomization part yet). But for some reason it doesn't output correctly.
<?php
$name = "pic.jpg";
$src = imagecreatefromjpeg($name);
list($width, $height, $type, $attr) = getimagesize($name);
$x_size = floor($width/32);
$y_size = floor($height/32);
$mixed = array();
$new_image = imagecreatetruecolor(32,32);
$x = 0;
$y = 0;
for($y = 0; $y < $height; $y+= 32) {
for($x = 0; $x < $width; $x+=32) {
imagecopy($new_image, $src, 0, 0, $x, $y, 32, 32);
array_push($mixed, $new_image);
}
}
$final_image = imagecreatetruecolor($width, $height);
$i = 0;
$x1 = 0;
$y1 = 0;
for($i = 0; $i < sizeof($mixed); $i++) {
$x1++;
if($x1 >= $x_size) {
$x1 = 0;
$y1++;
}
imagecopymerge($final_image, $mixed[$i], $x1, $y1, 0,0,32,32,100);
}
header('Content-Type: image/jpeg');
imagejpeg($final_image);
?>
Original Image:
http://puu.sh/236XS
Output:
http://puu.sh/236YO
If you can help it wouldbe greatly appreciated.
Thanks.
I solved my own question using the following code:
<?php
include("test.php");
//global variables
$name = "pic.jpg";
$size = 64;
$x = 0;
$y = 0;
$spots = array("0,0", "0,1", "0,2", "0,3",
"1,0", "1,1", "1,2", "1,3",
"2,0", "2,1", "2,2", "2,3",
"3,0", "3,1", "3,2", "3,3");
//open image from file (Original image)
$src = imagecreatefromjpeg($name);
//load image details
list($width, $height, $type, $attr) = getimagesize($name);
//calculate amount of tiles on x/y axis.
$x_size = floor($width/$size);
$y_size = floor($height/$size);
$new_image = imagecreatetruecolor($size,$size);
$final_image = imagecreatetruecolor($width, $height);
$used = array();
for($y = 0; $y < $height; $y+= $size) {
for($x = 0; $x < $width; $x+= $size) {
//generate random x/y coordinates
redo:
$spot = rand(0, sizeof($spots)-1);
if(!in_array($spot, $used)) {
$coords = explode(",", $spots[$spot]);
//grab 32x32 square from original image
imagecopy($new_image, $src, 0, 0, $x, $y, $size, $size);
//place 32x32 square into new image at randomly generated coordinates
imagecopy($final_image, $new_image, $coords[0]*$size, $coords[1]*$size, 0,0,$size,$size);
array_push($used, $spot);
} else {
goto redo;
}
}
}
//display final image
header('Content-Type: image/jpeg');
imagejpeg($final_image);
print_r($used);
?>
Might not be the most efficient code, but it works :)
i have this script for pixelize my images the script is working but i want more smooth edges:
$imgfile = 'batman.jpg';
$image = ImageCreateFromJPEG($imgfile);
$imagex = imagesx($image);
$imagey = imagesy($image);
$pixelate_amount = 10;
$tmpImage = ImageCreateTrueColor($imagex, $imagey);
imagecopyresized($tmpImage, $image, 0, 0, 0, 0, round($imagex / $pixelate_amount), round($imagey / $pixelate_amount), $imagex, $imagey);
$pixelated = ImageCreateTrueColor($imagex, $imagey);
imagecopyresized($pixelated, $tmpImage, 0, 0, 0, 0, $imagex, $imagey, round($imagex / $pixelate_amount), round($imagey / $pixelate_amount));
header("Content-Type: image/jpeg");
imageJPEG($pixelated, "", 100);
I have:
this produce:
is there anything i miss?
Here's what you need (script I currently use). This script is based from the script at http://www.talkphp.com/19670-post1.html:
function convertToPixel($im, $size) {
$size = (int)$size;
$sizeX = imagesx($im);
$sizeY = imagesy($im);
if($sizeX < 3 && $sizeX < 3) { // or you can choose any size you want
return;
}
for($i = 0;$i < $sizeX; $i += $size) {
for($j = 0;$j < $sizeY; $j += $size) {
$colors = Array('alpha' => 0, 'red' => 0, 'green' => 0, 'blue' => 0, 'total' => 0);
for($k = 0; $k < $size; ++$k) {
for($l = 0; $l < $size; ++$l) {
if($i + $k >= $sizeX || $j + $l >= $sizeY) {
continue;
}
$color = imagecolorat($im, $i + $k, $j + $l);
imagecolordeallocate($im, $color);
$colors['alpha'] += ($color >> 24) & 0xFF;
$colors['red'] += ($color >> 16) & 0xFF;
$colors['green'] += ($color >> 8) & 0xFF;
$colors['blue'] += $color & 0xFF;
++$colors['total'];
}
}
$color = imagecolorallocatealpha($im, $colors['red'] / $colors['total'], $colors['green'] / $colors['total'], $colors['blue'] / $colors['total'], $colors['alpha'] / $colors['total']);
imagefilledrectangle($im, $i, $j, ($i + $size - 1), ($j + $size - 1), $color);
}
}
}
header('Content-type: image/jpg');
$im = imagecreatefromjpeg($imgfile);
convertToPixel($im, 15);
imagejpeg($im, '', 100);
This will produce:
You can also change the value passed in convertToPixel to modify the pixel size.
)
Use imagecopyresampled() instead of imagecopyresized().
http://php.net/manual/en/function.imagecopyresampled.php