I want to reduce the quality of an animated GIF to reduce GIF filesize. Animation and dimensions should stay the same.
Is this even possible?
I've tried various Imagemagick functions, but with no luck. Maybe someone has done this?
This is just a logical thinking, but it would be cool, if something like this would work:
$gif = new Imagick($tempFilePath);
$gif = $gif->coalesceImages();
foreach ($gif as $frame) {
$frame->setImageCompression(8);
$frame->setImageCompressionQuality(10);
}
$gif = $gif->deconstructImages();
$gif->writeImages($tempFilePath, true);```
GIF does not use compression. So your compression arguments will not do anything. In ImageMagick command line, the simplest way is just to reduce the number of colors in the animation.
Input (Mount St. Helens colorized):
convert animation.gif -coalesce +dither -colors 64 -layers optimize animation2.gif
I am not an Imagick expert, but I think what you want is quantizeImages, which I believe will reduce colors for an animation or set of images. See also the example at quantizeImage to reduce the colors of one single image.
Note that I first use -coalesce to fill out the frames. I use +dither to avoid dithering when reducing colors. And finally I re-optimize the animation.
However, the better way is to use one common color map for all frames and use as few colors as possible. Then also do layer optimization on the animation. This can be done as follows on this simple (extremely small number) 3-color example.
Input (Mount St. Helens colorized):
3-color Color Table (enlarged for viewing):
convert xc:red xc:green1 xc:blue +append colortable.gif
convert animation.gif -coalesce +dither -remap colortable.gif -layers optimize new_animation.gif
More practically, you can create a reduced color table by collecting all the colors from all the combined animation frames, reduce the colors and then get the unique colors. For example:
convert animation.gif -coalesce +append +dither -colors 64 -unique-colors -depth 8 colortable2.gif
Then apply this color table to the animation
convert animation.gif -coalesce +dither -remap colortable2.gif -layers optimize new_animation2.gif
The file sizes are:
animation.gif --- 481 K
animation2.gif (64 colors) --- 479 K
new_animation (3 colors) --- 57 K
new_animation2 (64 colors) --- 393 K
For Imagick, see the following methods:
coalesce
remap
append
uniquecolors
quantizeimage for reduced colors
I was working on image filters using PHP, but I am unable to find some filters like those at https://pinetools.com/. In particular, the ones listed below:
Clip Image
Adjust channels
Change Image exposure
Vibrance
I couldn't find these filters' solution in PHP GD filters or in PHP Imagick, based upon ImageMagick.
Is there any solution for this. Are there any of these filters there that I could not find?
How do I apply these filters to an image in PHP Imagick?
I know the question is broad please don't devote it, I thought it strange to post a separate question for each filter?
I have worked out the equivalent of Pinetools clip image in ImageMagick commands for values between 0 and 50.
Input:
For example at 50, clip image produces the following:
The following ImageMagick command reproduces that:
convert lena.jpg -black-threshold 50% -white-threshold 50% clip_image_imagemagick.png
The functions to use in Imagick are:
http://us3.php.net/manual/en/imagick.blackthresholdimage.php
http://us3.php.net/manual/en/imagick.whitethresholdimage.php
I do not know Imagick, but looking at the documentation, it appears that it wants a threshold value as a color, so try "gray(50%)" when the clip image value is 50.
Similarly, I have worked out the equivalent of Pinetools Adjust colors.
Here is the result for Pinetools red adjust 50.
In ImageMagick, that would be:
convert lena.jpg -channel r -level 0x50% +channel adjust_red_50.png
And the Imagick command is:
http://us3.php.net/manual/en/imagick.levelimage.php
But I am not sure what the values are. I believe they may be number in the range of 0 to quantum range. So if your IM version is Q16, then 0 to 65535 and if Q8, then 0 to 255. So 50% in Q16 would be 65535/2=32767.5. So
levelImage (0, 1.0, 32767.5, $channel = Imagick::CHANNEL_RED );
For Pinetools exposure 50, I can come close using the ImageMagick command -evaluate add.
Pinetools Exposure 50:
The ImageMagick command would be:
convert lena.jpg -evaluate add 40% lena_add_40%.png
And for Pinetools Exposure 100:
And the ImageMagick command would be twice that:
convert lena.jpg -evaluate add 80% lena_add_80%.png
The Imagick command for 50 would likely be:
http://us3.php.net/manual/en/imagick.evaluateimage.php
evaluateImage(Imagick::EVALUATE_ADD, 26214);
where 65535*40/100=26214
For Pinetools Vibrance 50:
You can do that in ImageMagick by changing colorspace to HSL (or HCL or similar), then applying sigmoidal-contrast to the Saturation/Chroma channel.
A close equivalent would be:
convert lena.jpg -colorspace HSL -channel g -sigmoidal-contrast 3,0% +channel -colorspace sRGB tmp.jpg
In Imagick, you would change colorspace using:
http://us3.php.net/manual/en/imagick.transformimagecolorspace.php
Then apply sigmoidalcontrastImage to the Saturation channel which in HSL would be the green channel:
http://us3.php.net/manual/en/imagick.sigmoidalcontrastimage.php
Then convert the colorspace back to (s)RGB.
Note that sigmoidal contrast is non-linear. You want to set the mid-point to 0% so that the straight part of the curve is at 0 and the curved part that curves over to near flat is at the top right. So it is like a non-linear brightness control on the Saturation.
You won't find one-to-one matching of those filters. But you can get similar effects in Imagick (or ImageMagick directly) with the following, though argument control is different.
clip image is http://us3.php.net/manual/en/imagick.contraststretchimage.php
adjust channels is
http://us3.php.net/manual/en/imagick.levelimage.php
change exposure is also
http://us3.php.net/manual/en/imagick.levelimage.php
There is no vibrance exact equivalence, but you can change saturation using:
http://us3.php.net/manual/en/imagick.modulateimage.php
If you are on Unix-like systems, you can use PHP exec() and run some of my bash ImageMagick shell scripts. I have several for vibrance and exposure (called xposure) and one for brightness-contrast adjustment. See http://www.fmwconcepts.com/imagemagick/index.php
I'm using PHP Imagick to convert PNG images generated in PhantomJS to TIF CMYK,
for print purposes I need a flat Black (cmyk - 0,0,0,100) - the conversion generates blacks like (cmyk - 58,49,44,89).
I'm converting the images using color profile (section of my code below) -> the code is based on Convert image from RGB to CMYK with Imagick
is it possible to force a flat black with Imagick ? do you know any other tools that might help ?
thanks,
if ($has_icc_profile === false) {
$icc_rgb = file_get_contents( '/srgb_profiles' . '/sRGB.icc');
$image->profileImage('icc', $icc_rgb);
unset($icc_rgb);
}
// then we add an CMYK profile
$icc_cmyk = file_get_contents( '/cmyk_profiles'.'/JapanColor2002Newspaper.icc');
$image->profileImage('icc', $icc_cmyk);
UPDATE :
after checking online I think I'm looking for a UCR en.wikipedia.org/wiki/Under_color_removal method for ImageMagick - I found that convert old versions supported under color removal
-undercolor <undercolor factor>x<black-generation factor>
control undercolor removal and black generation on CMYK images.
This option enables you to perform undercolor removal and black generation on CMYK images-- images to be printed on a four-color printing system. You can con- trol how much cyan, magenta, and yellow to remove from your image and how much black to add to it. The standard undercolor removal is 1.0x1.0. You'll frequently get better results, though, if the percentage of black you add to your image is slightly higher than the percentage of C, M, and Y you remove from it. For example you might try 0.5x0.7. (http://www.chemie.fu-berlin.de/chemnet/use/suppl/imagemagick/www/convert.html) -
apparently the option is not supported anymore, I'm interested if anyone knows if UCR is the solution I'm looking for and if anyone knows if it's supported or if I'm supposed to use a different method to get the same result.
If you use ImageMagick's convert at the command line like this to generate a grayscale ramp, 1 pixel wide and 256 pixels tall, going from white to black and convert it to CMYK colorspace and then show it as text, you get what you want:
convert -size 1x256 'gradient:rgb(255,255,255)-rgb(0,0,0)' -colorspace cmyk txt:
# ImageMagick pixel enumeration: 1,256,65535,cmyk
0,0: (0%,0%,0%,0%) #0000000000000000 cmyk(0,0,0,0)
0,1: (0%,0%,0%,0.392157%) #0000000000000101 cmyk(0,0,0,1)
0,2: (0%,0%,0%,0.784314%) #0000000000000202 cmyk(0,0,0,2)
0,3: (0%,0%,0%,1.17647%) #0000000000000303 cmyk(0,0,0,3)
0,4: (0%,0%,0%,1.56863%) #0000000000000404 cmyk(0,0,0,4)
0,5: (0%,0%,0%,1.96078%) #0000000000000505 cmyk(0,0,0,5)
0,6: (0%,0%,0%,2.35294%) #0000000000000606 cmyk(0,0,0,6)
0,7: (0%,0%,0%,2.7451%) #0000000000000707 cmyk(0,0,0,7)
0,8: (0%,0%,0%,3.13725%) #0000000000000808 cmyk(0,0,0,8)
0,9: (0%,0%,0%,3.52941%) #0000000000000909 cmyk(0,0,0,9)
0,10: (0%,0%,0%,3.92157%) #0000000000000A0A cmyk(0,0,0,10)
...
...
0,249: (0%,0%,0%,97.6471%) #000000000000F9F9 cmyk(0,0,0,249)
0,250: (0%,0%,0%,98.0392%) #000000000000FAFA cmyk(0,0,0,250)
0,251: (0%,0%,0%,98.4314%) #000000000000FBFB cmyk(0,0,0,251)
0,252: (0%,0%,0%,98.8235%) #000000000000FCFC cmyk(0,0,0,252)
0,253: (0%,0%,0%,99.2157%) #000000000000FDFD cmyk(0,0,0,253)
0,254: (0%,0%,0%,99.6078%) #000000000000FEFE cmyk(0,0,0,254)
0,255: (0%,0%,0%,100%) #000000000000FFFF cmyk(0,0,0,255)
You must be doing something different - maybe this will help you work it out. I am guessing it is your ICC profiles but you can experiment with the above command.
If you just want to experiment with spot values, you can just have IM translate a single pixel like this:
convert -size 1x1 xc:#000000 -colorspace cmyk txt:
# ImageMagick pixel enumeration: 1,1,65535,cmyk
0,0: (0%,0%,0%,100%) #000000000000FFFF cmyk(0,0,0,255)
or maybe more simply like this:
convert -size 1x1 xc:#000000 -depth 8 -colorspace cmyk txt:
# ImageMagick pixel enumeration: 1,1,255,cmyk
0,0: (0,0,0,255) #000000FF cmyk(0,0,0,255)
Note the following though:
You must put profiles between input image and output image names on the command line.
If your image has no embedded profile, the first profile you give is applied to the input image and the second to the output image. If your input image does have a profile, the first profile you give is applied to the output image.
I have a flash which outputs a PNG file in 72DPI, I need to execute the following steps (not necessarily in that order) in order to make it ready for print:
Convert to 300DPI
Resize to 9x5 cm
Put cross (for cutting later) on it
Save as PDF - 300DPI
With my little of tutorial reading + knowledge in IM, I got this far:
1. convert -units PixelsPerInch IMAGE.PNG -resample 300 IMAGE_300DPI.png
2. convert IMAGE_300DPI.png -resize 1111x639 IMAGE_300DPI_correct_size.png
3. composite -gravity center IMAGE_300DPI_correct_size.png cross.png card_new_with_cross.png
4. convert card_new_with_cross.png card_new.pdf
When I execute stage #4 everything changes and gets enlarged as far as I can tell, any Ideas?
by the way - 2 files (sideA.png & cross.png) can be found at:
http://www.bikur.co.il/sideA.png <-- the image
http://www.bikur.co.il/cross.png <-- the `cross-
It would be great if someone can help me with it
DPI is a conversion factor, not a measurement. It's used to convert an image's intrinsic pixels into some display medium's pixel.
e.g. a 300 dpi printer has "pixels" that are 1/300 inches in size, while a 72dpi monitor has 1/72 inch sized pixels. A 100x100#72dpi image on a monitor would have to be printed out at about 417x417 printer pixels to have the same apparent size (300/72 = 4.16666)
So, whatever size your image is initially, to get a 9x5cm image # 300dpi, it'd have to be converted as follows:
9 x 5cm = 3.543 x 1.968 inches # 300dpi = 1063 x 591
I create template websites. If a client choose a blue or green or purple heading, I don't want to have to store all those different color variations of an image. I want to programmatically change the hue. I do not want to 'flood fill' it because that would remove any textures or bevels.
For example page you see I have accomplished exactly what I want.
http://sta.oursitesbetter.com/test/index.php
I have done this using Imagick modulateImage function.
HOWEVER, I am just throwing random 'Hue' values and not RGB values. I want to accomplish this same thing feeding RGB values. I need a function similar to modulateImage however it must take RGB as value and set the image to that hue.
I have studied for the past 5 hours and cannot figure out how to do it. I need help.
Has any of the gurus of StackOverflow got a PHP Imagick solution to this color quandary?
From Wikipedia: Hue #Computing hue from RGB:
$hex=(sqrt(3)*($green-$blue)) /
(2*($red-$green-$blue));//$red, $green and $blue are each a value in the range 0->255
$img->modulateImage(100, 100, intval($hex*100/256));
//probably 256->100 value above will work, if didn't , try with the following insead.
//$img->modulateImage(100, 100, $hex);
Another option might be to use ImageMagick to create a single pixel image in the RGB colour you want and then see what ImageMagick makes that in HSL colorspace. Say your RGB values are 25,126,200, you could do this:
convert -size 1x1! xc:rgb\(25,126,200\) -colorspace HSL txt:-
# ImageMagick pixel enumeration: 1,1,65535,hsl
0,0: (57.0474%,77.7783%,44.1184%) #920AC71C70F1 hsl(57.0474%,77.7783%,44.1184%)
The following equivalent methods are maybe a little more succinct:
convert xc:rgb\(25,126,200\) -format "%[fx:100*p{0,0}.hue]" info:
57.0476
convert xc:rgb\(25,126,200\) -format "%[fx:100*hue]" info:
57.0476
So, IM makes that a Hue of 57.0474%. Of course you don't need to run that and parse the text output, I am only doing that to demonstrate the concept - you can access the pixel directly in PHP.