Apply absolute contrast and brightness using Imagemagick - php

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

Related

FFmpeg - Resize Largest Video Dimension to 320

I'm trying to dynamically change the resolution of videos uploaded to a server via PHP, using FFmpeg. IE, I want to preserve portrait or landscape orientation - if Y is higher than X, I want to change Y to 320 and X to a corresponding value, and vice versa. I'm not having trouble with the resizing itself - it's quite straightforward, actually. What I'm having trouble with is detecting which dimension is larger.
I grabbed this solution off StackOverflow: how to check if video is landscape or portrait using ffmpeg php?
However, it doesn't appear to be working. While I track down what isn't working - I'm assuming the way the output is formatted has changed since that solution was posted, and it now needs to be parsed differently - I wanted to ask if there was a better way to do this. I'm open to using FFmpeg or a PHP-based solution.
ffmpeg -i input.jpg -vf 'scale=320:320:force_original_aspect_ratio=decrease' output.png
According to FFmpeg documentation, the force_original_aspect_ratio option is useful to keep the original aspect ratio when scaling:
force_original_aspect_ratio
Enable decreasing or increasing output video width or height if
necessary to keep the original aspect ratio. Possible values:
disable
Scale the video as specified and disable this feature.
decrease
The output video dimensions will automatically be decreased if
needed.
increase
The output video dimensions will automatically be increased if
needed.
Use decrease to make the largest dimension to 320, or use increase to make the smallest dimension to 320.
Have a look at the resizing page on the FFmpeg wiki. You basically want to look specifically at this section:
Sometimes there is a need to scale the input image in such way it fits
into a specified rectangle, i.e. if you have a placeholder (empty
rectangle) in which you want to scale any given image. This is a
little bit tricky, since you need to check the original aspect ratio,
in order to decide which component to specify and to set the other
component to -1 (to keep the aspect ratio). For example, if we would
like to scale our input image into a rectangle with dimensions of
320x240, we could use something like this:
ffmpeg -i input.jpg -vf scale="'if(gt(a,4/3),320,-1)':'if(gt(a,4/3),-1,240)'" output_320x240_boxed.png
You can obviously use this for videos as well as for images.
You can use a if statement to select the larger one
-vf scale='if(gt(iw,ih),320:-2)':'if(gt(iw,ih),-2:320)'
FYI, the correct way to do this is to use FFprobe, which comes with FFmpeg.
https://www.ffmpeg.org/ffprobe.html

CSS brightness/contrast at the server side

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

Radial gradients with opacity in PHP

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

When dealing with GD Library unwantedly altering colors

I'm merging multiple small images into a rectangular mosaic.
When dealing with a small number of source images it turns out fine:
But when dealing with a larger number of sources it turns out a sepia like effect:
Is there any technique I should be used to preserve the colors?
My method for merging the images is essentially running a script that loops through the source images using imagecreatefromjpeg() to grab it, followed by imagecopy() to merge the source onto the collective destination image (and runs until all images have been added/placed).
instead of using imagecreate() as my starting point, I changed to imagecreatetruecolor() and it has resolve the color loss issue.

Image comparison with php + gd

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.

Categories