Looking for answer for 2 weeks. I have a tool which allows to adjust images' contrast and brightness directly in the web browser and use CSS3 properties to show result. But I should also apply these modification to original JPG at the server-side and output it back to user.
How can I do it? I am using PHP+Imagemagick, but can not find a way to do this conversion. Please help me.
I found a great function of ImageMagick which allows us to do anything with brightness and contrast. It is "-level".
But it doesn't allow to apply CSS3 brightness and contrast values directly. Thus I made a great investigation and calculate special formula to transfer CSS brightness and contrast values to "black point" and "white point" parameters of "-level" option. Please check this page (sorry, russian language, but you can use google translate). Roll to the bottom of page if you don't want to read all these equations.
The CSS3 brightness filter simply multiplies the color values by the given constant.[1][2] To achieve the same effect with Imagemagick, use -evaluate Multiply[3]. Alternatively, -function Polynomial[4] can be used for the same effect. Other features such as -level[5][6] and -brightness-contrast[7][8] are less appropriate, because they multiply the color by the inverse of the given constant.
The CSS property filter: brightness(80%) corresponds to the Imagemagick option -evaluate Multiply .8.
The CSS property filter: brightness(120%) corresponds to the Imagemagick option -evaluate Multiply 1.2.
Setting options for Imagemagick in PHP (or migrating from PHP to something better) is an exercise for the reader.
You need to transfer your client brightness settings and then apply them to original JPG with
bool Imagick::modulateImage ( float $brightness , float $saturation , float $hue )
function. More this
Related
I have a tool which allows to justify contrast and brightness of image online using CSS3 filters. Thus I got two values of brightness and contrast from 0 to [inf] which means "1" is no change in brightness/contrast.
Next step, I need to apply these changes to image physically using Imagemagick. I've digged a ton of docs but not found how I can apply these 2 values to image.
It is relatively simple way to apply brightness and contrast corrections to image file using command-line Imagemagick?
convert -brightness-contrast 10X10 1.png 2.png
I need to create a PNG radial gradient with opacity. I've looked through GDLib but I can't see a way to generate radial gradients. Does anyone know of a way with GDlib or any other graphics library for PHP?
I suppose worst-case I could generate it pixel-by-pixel using GDLib but how does one even start to do the math on that?
The goal is to generate sexy lighting effect background PNGs for web pages. An example of the effect can be seen on the header here which uses this background image. I've tried generic white lighting effect PNGs but it doesn't look anywhere near as good as tinted lighting, so my generated PNGs will take into account the website's color scheme.
I assume server-side is the way to go because browser support for CSS radial gradients is so patchy.
Why not use a combination of imagecolorallocatealpha() and imageellipse() or imagefilledellipse()?
Edit:
See this class for an example of what I mean. You should be able to extend this to support alpha.
Edit2:
I have made some modifications to the class above to yield alpha support. It's not perfect, but it works for ellipses and such:
http://codepad.org/1eZ3Km0J
the classic video game trick is to apply a gradient texture, rather than compute the light. this is a perfect use for the technique.
make a grayscale gradient at a large-ish pixel dimension (2048px square is common) and several smaller ones (1024,512,256px etc) pick the closest one for your need (scaling up may exaggerate banding, scaling down may introduce moire).
use php gd function such as imagecopymerge. depending on intent, you could store the result on first use.
I suppose worst-case I could generate
it pixel-by-pixel using GDLib but how
does one even start to do the math on
that?
The math is easy, alpha = max_alpha - (distance_to_center / radius) where the distance is Euclidean, i.e. sqrt( (x1-x2)^2 + (y1-y2)^2 ).
First off, I don't mean google image search!
I would like to give users the ability to select a hex color value and then have a search programatically return (from specified sites/directories online) images where the dominant color is the color they specified (or close to it).
Is there a technology that can do this? I'd prefer PHP/MySQL, but I'd be willing to use other languages if it would be simpler.
EDIT
Taking several suggestions, I managed to find this: http://www.coolphptools.com/color_extract which does a decent job at extracting the most common colors from the image.
The next step is calculating distance from the extracted colors to the color being searched for. I have no issue implementing it except I'm unclear on the best way to calculate the color distance?
I've scoured this site and google for a concrete answer, but come up dry. The tool above extracts colors into hex color codes. I am currently converting this to RGB and using those.
Should I attempt to convert RGB to Y'UV? I'm attempting that by using:
sqrt(((r - r1) * .299)^2 + ((g - g1) * .587)^2 + ((b - b1) * .114)^2)
(based on an answer here: RGB to closest predefined color)
It's not very accurate. What should I swap that color distance formula with so it calculates accurate color distance (to the human eye)?
Interesting.
The first problem is: "What is the dominant colour of an image?" Maybe the one most pixels have. What do you do with similar shades of the same colour? Would you cluster around similar colours?
I would implement it this way:
Grab all images inside your search paths. Cluster the colors used in each of them and the biggest cluster is the dominant color. You will have to play around a bit with cluster sizes and number of clusters. If this color is within a certain range of hue, saturation and brightness of your searched color it is a match.
Firstly, I wonder how can you crawl over the sites/directories to search for a particular image color, unless you have a big list of websites. If it isn't related to your question then just ignore it.
Back to your question, I personally think this is an interesting question as well. Since it requires quite a few research, I just want to point out some ideas for you to reference.
What you need to do is to get user-specified hex colors and convert them into RGB colors, because most of the image functions in PHP that I know only work with RGB. Now, if you have a list of directories that you can search for, then just crawl over them and use some basic functions to get hold of the desired webpage' contents (e.g. file_get_contents, or cURL). Once you have the contents of a specific page, you will need to use DOM functions to get images' URLs from that page (you can work it out yourself, using: getElementsByTagName() and getAttribute()). Now assuming that you are holding a list of image URLs, now you need to get their colors and try to match them with your user-specified colors (remember to convert everything into RGB).
In PHP we have a very convenient GD library that works with images. If your server support GD2 then you can have a look at imagecolorclosest(). This function "Returns the index of the color in the palette of the image which is "closest" to the specified RGB value". Note that the function only returns the closest match (not exactly match), so you have to do some comparisons to choose the right images (I believe this is easy because you now have RGB colors with very handy values to work with, say, using some subtraction and adjustment method).
Moreover, not only the images, when you have a specific page content, you can try to search for the color scheme of that page (by getting its "background-color" value), there are quite a few details that you can get and play around with :) Of course, an image's color is somehow related to its page's styling scheme colors, think logically wider.
If I'm saying something not clear, don't hesitate to comment on my reply :)
Happy coding.
I have a whole bunch of images of illustrations that I would like to crop to a smaller preview size.
The problem is that I want to crop them to show an "interesting" part of the illustration (ie avoid areas of whitespace).
The images typically have a flat color or a subtle gradient for the background. They are mostly vector style artwork with fairly distinct shapes.
Here are some examples: link ;-)
I've been thinking about using some sort of image feature detection algorithm with a sliding window to find the area with the greatest number of features.
I'm implementing this in PHP, but I don't mind implementing it myself if there isn't a library or extension available.
Ideas?
ImageMagick has a trim operation. It's available as a library but I don't know how hard it is to use from PHP. There are some PHP interfaces.
OK, so here's what I would've done, after looking at the examples:
Sum all rows and all columns of each image. You'll get two arrays, both looking like this:
/-----\ /--\
_/ -- |
___- \_________
By looking at these arrays for a few images, find a suitable threshold (probably something just above zero). Then the leftmost and the rightmost crossing of this threshold is where you have to crop. I hope I've managed to make it clear enough, if not -- ask!
Here's a fairly simple approach using an edge-detection filter, and then cropping around the center-of-edginess of the image to generate a thumbnail. It works pretty well on most images, but not if there are more than one subject. I'm open to suggestions on other ways of identifying the "interesting" points in a source image.
Well, you might want to consider just using an edge detection algorithm. Pick the area with the largest number of edges. Give higher weight to edges that are not blurry (as they may be from the background).
ImageMagick for PHP has automated generation of thumbnails. This SO question has a link to an ImageMagick auto-crop operator, and I'm not sure, but I think this is the PHP interface to it.
From the link:
bool Imagick::trimImage ( float
$fuzz )
Remove edges that are
the background color from the image.
For more general "interestingness", maybe try an inverse of seam carving (to find the highest energy, rather than lowest energy areas).
A CLI program using http://pecl.php.net/package/imagick:
<?php
dl('imagick.so');
$img = new Imagick();
$img->readImage($argv[1]);
# (* 0.0: exact match; * 1.0: crop entire image)
$fuzz = current($img->getQuantumRange()) * 0.25;
$img->trimImage($fuzz);
$img->writeImage($argv[2]);
?>
It should work good enough, as long as the image doesn't have a frame around its border.
Drupal has a project called smartcrop, which has PHP code to find highest entropy and "interesting" areas in images. See the output examples.
You should be able to use the functions in the module and the library in none-Drupal projects too.
What's the best approach to comparing two images with php and the Graphic Draw (GD) Library?
This is the scenario:
I have an image, and I want to find which image of a given set is the most similar to it.
The most similar image is in fact the same image, not pixel perfect match but the same image.
I've dramatised the difference between the two images with the number one on the example just to ease the understanding of what I meant.
Even though it brought no consistent results, my approach was to reduce the images to 1px using the imagecopyresampled function and see how close the RGB values where between images.
The sum of the values of deducting each red, green and blue decimal equivalent value from the red, green and blue decimal equivalent value of the possible match gave me a dissimilarity index that, even though it didn't work as expected since not always the most RGB similar image was the target image, I could use to select an image from the available targets.
Here's a sample of the output when comparing 4 images against a target image, in this case the apple logo, that matches one of them but is not exactly the same:
Original image:
Red:222 Green:226 Blue:232
Compared against:
http://a1.twimg.com/profile_images/571171388/logo-twitter_normal.png
Red:183 Green:212 Blue:212 and an index of similarity of 56
Red:117 Green:028 Blue:028 and an index of dissimilarity 530
Red:218 Green:221 Blue:221 and an index of dissimilarity 13 Matched Correctly.
Red:061 Green:063 Blue:063 and an index of dissimilarity 491
May not even be doable better with better results than what I'm already getting and I'm wasting my time here but since there seems to be a lot of experienced php programmers I guess you can point me in the right directions on how to improve this.
I'm open to other image libraries such as iMagick, Gmagick or Cairo for php but I'd prefer to avoid using other languages than php.
Thanks in advance.
I'd have thought your approach seems reasonable, but reducing an entire image to 1x1 pixel in size is probably a step too far.
However, if you converted each image to the same size and then computed the average colour in each 16x16 (or 32x32, 64x64, etc. depending on how much processing time/power you wish to use) cell you should be able to form some kind of sensible(-ish) comparison.
I would suggest, like middaparka, that you do not downsample to a 1 pixel only image, because you loose all the spatial information. Downsampling to 16x16 (or 32x32, etc.) would certainly provide better results.
Then it also depends on whether color information is important or not to you. From what I understand you could actually do without it and compute a gray-level image starting from your color image (e.g. luma) and compute the cross-correlation. If, like you said, there is a couple of images that matches exactly (except for color information) this should give you a pretty good reliability.
I used the ideas of scaling, downsampling and gray-level mentioned in the question and answers, to apply a Mean Squared Error between the pixels channels values for 2 images, using GD Library.
The code is in this answer, including a test with those ideas.
Also I did some benckmarking and I think the downsampling could be not needed in those little images, cause the method is fast (being PHP), just a fraction of a second.
Using middparka's methods, you can transform each image into a sequence of numeric values and then use the Levenshtein algorithm to find the closest match.