PHP gd library crop white background to transparent png - php

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?

Related

PHP Remove black bar from image

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);

Black background instead of transparent on PNG images when processing them

I'm having a script that is detecting weather it's a png image or jpeg, and also "removing" whitespace around images.
But I get a black background on all .png images. Why is that?
//load the image
$logo = $json['Logotype'];
$image_type = getimagesize($logo);
if($image_type['mime']=='image/jpeg') {
$img_type = 'jpeg';
$img = imagecreatefromjpeg($logo);
} elseif($image_type['mime']=='image/png') {
$img_type = 'png';
$img = imagecreatefrompng($logo);
}
//find the size of the borders
$b_top = 0;
$b_btm = 0;
$b_lft = 0;
$b_rt = 0;
//top
for(; $b_top < imagesy($img); ++$b_top) {
for($x = 0; $x < imagesx($img); ++$x) {
if(imagecolorat($img, $x, $b_top) != 0xFFFFFF) {
break 2; //out of the 'top' loop
}
}
}
//bottom
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; //out of the 'bottom' loop
}
}
}
//left
for(; $b_lft < imagesx($img); ++$b_lft) {
for($y = 0; $y < imagesy($img); ++$y) {
if(imagecolorat($img, $b_lft, $y) != 0xFFFFFF) {
break 2; //out of the 'left' loop
}
}
}
//right
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; //out of the 'right' loop
}
}
}
//copy the contents, excluding the border
$newimg = imagecreatetruecolor(
imagesx($img)-($b_lft+$b_rt), imagesy($img)-($b_top+$b_btm));
switch ($img_type)
{
case "png":
// integer representation of the color black (rgb: 0,0,0)
$background = imagecolorallocate($newimg, 0, 0, 0);
// removing the black from the placeholder
imagecolortransparent($newimg, $background);
// turning off alpha blending (to ensure alpha channel information
// is preserved, rather than removed (blending with the rest of the
// image in the form of black))
imagealphablending($newimg, false);
// turning on alpha channel information saving (to ensure the full range
// of transparency is preserved)
imagesavealpha($newimg, true);
break;
case "gif":
// integer representation of the color black (rgb: 0,0,0)
$background = imagecolorallocate($newimg, 0, 0, 0);
// removing the black from the placeholder
imagecolortransparent($newimg, $background);
}
imagecopy($newimg, $img, 0, 0, $b_lft, $b_top, imagesx($newimg), imagesy($newimg));
//finally, output the image
header("Content-Type: image/" . $img_type . "");
imagejpeg($newimg);
This $background = imagecolorallocate($newimg, 0, 0, 0); is for black background
use $background = imagecolorallocatealpha($newimg, 255, 255, 255); instead

GD Image Library merge 2 images with "Collision Detection"

I have two images, large text on white background. The length varies but the text is always aligned to the left, so there is basically free space on the right side of each image. I now want to merge these two images into one and move them as closely together as possible without having the texts "collide".
I thought of somehow checking on a per pixel column base if there's another color than white (starting from the right side), so I know after how many pixels the text starts.
Found the solution, neat function to strip all the whitespace from an image:
function stripWhitespace($img) {
//find the size of the borders
$b_top = 0;
$b_btm = 0;
$b_lft = 0;
$b_rt = 0;
//top
for(; $b_top < imagesy($img); ++$b_top) {
for($x = 0; $x < imagesx($img); ++$x) {
if(imagecolorat($img, $x, $b_top) != 0xFFFFFF) {
break 2; //out of the 'top' loop
}
}
}
//bottom
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; //out of the 'bottom' loop
}
}
}
//left
for(; $b_lft < imagesx($img); ++$b_lft) {
for($y = 0; $y < imagesy($img); ++$y) {
if(imagecolorat($img, $b_lft, $y) != 0xFFFFFF) {
break 2; //out of the 'left' loop
}
}
}
//right
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; //out of the 'right' loop
}
}
}
//copy the contents, excluding the border
$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;
}
From here: Crop whitespace from image in PHP

PHP replace a color pixel by a transparente one

I want to make in a easy way a logo with solid backgroung with a transparent one, so I decide to take the first pixel and set that color on all the image as transparent, I know is not the best solution for all but I think covers most cases.
The problem is the pixel it's coloring black insted transparent, this is my code:
$im = $this->loadImage($targetFile);
$this->replaceImageColor($im, imagecolorat($im, 0, 0), imageColorAllocateAlpha($im, 255, 255, 255, 127));
imagepng($im, 'test.png');
And my class functions:
function loadImage($imagePath) {
$resource = false;
if( strstr($imagePath, '.jpg') || strstr($imagePath, '.jpeg') )
$resource = #imagecreatefromjpg($imagePath);
if( strstr($imagePath, '.png') )
$resource = #imagecreatefrompng($imagePath);
return $resource;
}
function replaceImageColor($img, $from, $to) {
// pixel by pixel grid.
for ($y = 0; $y < imagesy($img); $y++) {
for ($x = 0; $x < imagesx($img); $x++) {
// find hex at x,y
$at = imagecolorat($img, $x, $y);
// set $from to $to if hex matches.
if ($at == $from)
imagesetpixel($img, $x, $y, $to);
}
}
}
Finally I solved it in this way
$im = $this->loadImage($targetFileIcon);
$out = $this->transparentColorImage($im, imagecolorat($im, 0, 0));
imagepng($out, 'test.png');
imagedestroy($im);
imagedestroy($out);
function loadImage($imagePath) {
$resource = false;
if( strstr($imagePath, '.jpg') || strstr($imagePath, '.jpeg') )
$resource = #imagecreatefromjpg($imagePath);
if( strstr($imagePath, '.png') )
$resource = #imagecreatefrompng($imagePath);
return $resource;
}
function transparentColorImage($img, $color) {
// pixel by pixel grid.
$out = ImageCreateTrueColor(imagesx($img),imagesy($img));
imagesavealpha($out, true);
imagealphablending($out, false);
$white = imagecolorallocatealpha($out, 255, 255, 255, 127);
imagefill($out, 0, 0, $white);
for ($y = 0; $y < imagesy($img); $y++) {
for ($x = 0; $x < imagesx($img); $x++) {
// find hex at x,y
$at = imagecolorat($img, $x, $y);
// set $from to $to if hex matches.
if ($at != $color)
imagesetpixel($out, $x, $y, $at);
}
}
return $out;
}
I created a true image with alpha channel and no alphablending.
BR

How to pass filename to function and loop through and crop images?

I'm trying to crop a list of images. The list is stored in a txt file.
I run through the txt file and store the img urls into an array
Array ( [0] => img001.jpg [1] => img002.jpg [2] => img003.jpg [3] => img004.jpg )
The .php, .txt, and .jpg images are all in the same folder and there a IMG2 subfolder.
I'm running this locally.
I was getting an error loading file, but now I just get a blank screen.
Can someone help me make this loop through the files in an array crop them. I realize that in the example below i'm just sending one value from $lines[1], thats because I can't even get that to work.
Once that works then adding a FOR loop should be straight forward.
Thanks
<?PHP
error_reporting(E_ALL);
ini_set('display_errors', '1');
$fd = fopen ("files.txt", "r");
while (!feof ($fd))
{
$buffer = fgets($fd, 4096);
$lines[] = $buffer;
}
fclose ($fd);
print_r($lines);
$imgurl = $lines[1];
processImage($imgurl); //or below line doesn't work
//foreach ($lines as $imgurl) processImage(trim($imgurl));
Function processImage($imgurl) {
//load the image
$img = #imagecreatefromjpeg($imgurl);
if (!$img) { /* See if it failed */
$img = imagecreatetruecolor(150, 30); /* Create a black image */
$bgc = imagecolorallocate($img, 255, 255, 255);
$tc = imagecolorallocate($img, 0, 0, 0);
imagefilledrectangle($img, 0, 0, 150, 30, $bgc);
/* Output an errmsg */
imagestring($img, 1, 5, 5, "Error loading $imgurl", $tc);
}
return $img;
$b_top = 0;
$b_btm = 0;
$b_lft = 0;
$b_rt = 0;
//top
for(; $b_top < imagesy($img); ++$b_top) {
for($x = 0; $x < imagesx($img); ++$x) {
if(imagecolorat($img, $x, $b_top) != 0xFFFFFF) {
break 2; //out of the 'top' loop
}
}
}
//bottom
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; //out of the 'bottom' loop
}
}
}
//left
for(; $b_lft < imagesx($img); ++$b_lft) {
for($y = 0; $y < imagesy($img); ++$y) {
if(imagecolorat($img, $b_lft, $y) != 0xFFFFFF) {
break 2; //out of the 'left' loop
}
}
}
//right
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; //out of the 'right' loop
}
}
}
//copy the contents, excluding the border
$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));
//finally, output the image
header("Content-Type: image/jpeg");
imagejpeg($newimg);
// Save the image
$newname = "t_".$imgurl;
imagejpeg($newimg, $newname);
// Free up memory
imagedestroy($newimg);
imagedestroy($img);
}
?>
Somewhere at the top of your image processing function, you have the line:
return $img;
So that´s as far as it gets, it always returns from the function from there, the code after that is never reached.
Just removing that line should get you a lot further.

Categories