Imagemagick desaturate black/white? - php

Would like to turn this into black and white.. can't figure out what to use from imagick..
$handle_data = file_get_contents('http://www.bungie.net/Stats/Reach/Nightmap.ashx');
//http://www.bungie.net/Stats/Halo3/Nightmap.ashx
$img = new Imagick();
$img->readImageBlob($handle_data);
$img->writeImage('nightmap/'.$time.'.gif');

Using Imagick::modulateImage could be a quick&dirty solution. Dirty because color theory is a rather complex field, and there can be done more to create grayscale images than just desaturating the image (like applying different weights to the single color channels).
bool Imagick::modulateImage (float $brightness , float $saturation , float $hue)
Given an image, keep brightness and hue at 100%, while setting saturation to 0%. There is an example at the bottom of the documentation page that does exactly that.

There's a much better (and just as simple) solution: $im = $im->fxImage('intensity');
That applies a function to the image, where intensity is equal to 0.299*red+0.587*green+0.114*blue.
That formula is based on how our eyes are more sensitive to different colours, and as such the difference between that and a "flat" grayscale image really is night and day.
More details here:
http://php.net/manual/en/imagick.fximage.php
http://www.imagemagick.org/script/fx.php

Related

How does IMG_CROP_THRESHOLD work compared to IMG_CROP_SIDES?

What is the main difference between IMG_CROP_THRESHOLD and IMG_CROP_SIDES?
I have been trying to roughly crop the background out of a photo of a document, but either way I am not able to get the outcome I am aiming for.
Also, I took the null, 16777215 from https://www.php.net/manual/en/function.imagecropauto.php, but I honestly don't understand what they actually do. I would have expected to put something like 0.1, #FFFFFF to crop out a background that is white or close to it. What is the null, 16777215 all about?
$cropped = imagecropauto($img, IMG_CROP_THRESHOLD, null, 16777215);
$cropped = imagecropauto($img, IMG_CROP_SIDES);
IMG_CROP_SIDES works by automatically calculating the average color of the pixels around the border of an image an crops off anything within 50% of that value. -
Correction
IMG_CROP_SIDES uses gdGuessBackgroundColorFromCorners which essentially finds the distance from the corner colors to the closest color in the existing palette and then uses this distance for pixel selection to crop.
IMG_CROP_THRESHOLD does NOT calculate the background color but it does provide more flexibility in this calculation as it allows the dev to specify the border color and also the threshold. Documentation is poor on the threshold stating it's a percentage however this actually means an integer or float between 0 and 100 (e.g. not 0.25 but 25).
If IMG_CROP_SIDES is cutting into a bright image, use IMG_CROP_THRESHOLD instead.
For example with a 25 threshold - Approx anything lighter than #E8E8E8 is border.
$cropped = imagecropauto($img, IMG_CROP_THRESHOLD, 25, 16777215);
https://github.com/libgd/libgd/blob/167ea1f4f0003f3e9f7ca1e586189e99cf33d47f/src/gd.c#L460
https://github.com/libgd/libgd/blob/1e47a89a65d49a9003d8365da4e26a7c1a32aa51/src/gd_crop.c#L112

change color range image

I am using PHP-Imagick to convert a PDF into images, which works fine.
A simplified example:
$im = new imagick();
$im->setResolution(250,250);
$page = $pdfPath."[0]";
$im->readImage($page);
if($im->getImageColorspace() == Imagick::COLORSPACE_CMYK)
{
$im->transformImageColorspace(Imagick::COLORSPACE_SRGB);
$im->autoLevelImage();
}
$im->setImageFormat('jpg');
$im->setImageCompression(imagick::COMPRESSION_JPEG);
$im->setImageCompressionQuality(90);
$im->writeImage("page1.jpg");
However the coloring seems to differ from the original PDF, for example (see image)
left side is original PDF.
right side the rendered image, which has different colors than the original.
It seems that the original color of dark-pink turns into purle. Also red colors seem to saturate.
I have tried the following, but none worked:
reduce saturation (e.g. $im->modulateImage(100, 80, 100); ) But this causes red to become orange and yellow colors to turn greenish.(see example below)
playing around with image filter (e.g. imagefilter($im, IMG_FILTER_COLORIZE,100, 0, 0); ), but this also changes all colors.
Thinking it had to do with differences between CMYK and RGB, I have added $im->transformImageColorspace() doesn't do anything to fix this.
playing with various hue filters, but these change all colors of the image also.
Question: it seems I need to reduce the redness of the image? (I think it's the excessive red color causing the difference) without affecting the other colors, so that for example yellow remains yellow. Is there a way to do this in PHP?
The solution is to add the following line before reading the image:
The code should be:
$im->setColorspace(Imagick::COLORSPACE_SRGB);
$im->readImage($page);

How to create png from array of pixel color data in PHP?

Lets say I have an arrays of pixels. Basically an array of this data {x,y,r,g,b,a} for each pixel.
How would I go about converting all this data into an actual image file (png preferably)?
Could not find a solution. Any help would be very appreciated.
I had some time to code up a little example. You should be able to see and note that:
the red component increases towards the bottom of the image
the green component increases towards the right of the image
the blue component is absent
the alpha channel is random and between 0 (opaque) and 127 (fully transparent)
// Define width and height
$w=800;
$h=600;
// Create truecolour image so we can have infinitely many colours rather than a limited palette
$img=imagecreatetruecolor($w,$h);
imagesavealpha($img,true);
imagealphablending($img,false);
// Iterate over all pixels
for($y=0;$y<$h;$y++){
for($x=0;$x<$w;$x++){
$r = round(255*$y/$h);
$g = round(255*$x/$w);
$b = 0;
$alpha = rand(0,127);
$color = imagecolorallocatealpha($img,$r,$g,$b,$alpha);
imagesetpixel($img,$x,$y,$color);
}
}
// Save result
imagepng($img,"result.png");
I'll admit I haven't actually used this API, but looks like PHP has what you're looking for.
You create an image identifier with imagecreate or one of the related functions, then color in each pixel with imagesetpixel, using a color identifier created with imagecolorallocatealpha. From there you should be able to output as a PNG with imagepng.
It's worth noting that this image library seems to support drawing lines and shapes and other structures higher than the per-pixel level, so I'd also look into whether your code necessarily needs to build a big pixel array, rather than drawing the image some other way.

text resize with php while using GD functions

I did found a topic similar to this, but I do not know if the solution is the same. So here is my question:
I'm using the GD functions to bild a web card generating program. The thing is that the card's backgound is generating by the $image = imagecreatefrompng(); function.
The card need's also a $cardname as "title" and a $desription as desription. For that I used the imagettftext(); function. But there is a problem, the card's size is 333x485, I need the text to be resized in order to fit in the background without resizing its height, but only the width!
To be more to the point, the $cardname should have width = 240 and height = 34, but if it doesn't fit, it goes off the background, I need a function that will resize its width in order to fit in 240px and leave the height to 34px always!
To understand it more look here: http://yugiohcardmaker.net. in the "name" you can add as much text you like, it will always fit in and in the right width and height!
I'm not going to try and code this as it will take too long, but here's the basic process:
Get the size of the bounding box for your text with imagettfbbox();
Create a new image with imagecreatetruecolor();
Write your text into your new image with imagettftext();
Use imagecopyresampled() to copy the new image with your text to your existing card, setting the parameters to shrink the width but not the height.
Note: the bounding box parameters returned by imagettfbbox()) can be fiddly to work with
You'll also need to be careful about alphablending and background colors to ensure that only your text pixels are copied.
Good luck!

Rotate image *without* resizing it

I would like to rotate an image (with a user-defined angle of rotation), but without making the image smaller.
is what happens already, saving the shaded area as a smaller image
is what I would like, the dashed line being the new image size.
The server has PHP 5.3+. Links, code and explanations all very welcome.
This is not complete answer but I would take the four corners as coordinates rotate them by your angle and then calculate the new bounding box based on the extent of the new coordinates.
(assuming coordinates with origin on the bottom left).
corners = rotate_each ( [(left,top) (left,bottom), (right,top), (right,bottom)], angle)
new_bb_left = min([corners[0].x, corners[1].x, corners[2].x, corners[3].x])
new_bb_right = max([corners[0].x, corners[1].x, corners[2].x, corners[3].x])
new_bb_bottom = min([corners[0].y, corners[1].y, corners[2].y, corners[3].y])
new_bb_top = max([corners[0].y, corners[1].y, corners[2].y, corners[3].y])
This could be a way to do it. Calculate the diagonal width.
PHP has a Square root function: http://se2.php.net/manual/en/function.sqrt.php
In that way you should have the diagonal width which you could apply on the transformed image.
There are many solutions including the trigonometric formulas but this library seems to be the shortcut.
http://wideimage.sourceforge.net/
Example: http://wideimage.sourceforge.net/wp-content/current/demo/index.php?demo=rotate&output=preset%20for%20demo&colors=255&dither=1&match_palette=1

Categories