I'm trying to write a PHP function to convert an SVG image without any antialiasing (so that the final PNG is blocky and contains only the colours specified in the SVG).
The command line equivalent is:
convert +antialias /path/to.svg /path/to.png
I'm assuming that I need to use PHP's Imagick::setOption method to pass in "+antialias", but the documentation is very sparse.
The following snippet will write a PNG file, but none of the options prevents antialiased pixels being rendered:
$image = new Imagick();
// None of these have any affect - output image is always antialiased.
$image->setOption('+antialias', true);
$image->setOption('-antialias', true);
$image->setOption('+antialias', 'true');
$image->setOption('-antialias', 'true');
$image->setOption('antialias', true);
$image->setOption('antialias', false);
$image->setOption('antialias', 'true');
$image->setOption('antialias', 'false');
$image->readImage('/path/to.svg');
$image->writeImage('/path/to.png');
Any help would be great, thanks.
That is not a good way to anti-alias a vector file such as SVG. The proper way in command line would be to set the desired density before reading the file and then resize back to compensate for a large magnification when using a large density. So for example
convert -density 288 image.svg -resize 25% image.png
Nominal density (default) is 72. So 288 = 72*4. Thus we resize afterwards by 1/4 = 25%, unless you want a larger output. Then resize by a larger value.
In PHP Imagick, you can create a new Imagick() instance. Then set the desired density. Then read the input SVG. Then resize. Then set the PNG format and save to disk. See setImageResolution for setting the density in Imagick. See https://www.php.net/manual/en/imagick.setimageresolution.php
I don't think what you want is possible, unfortunately. ImageMagick shells out to Inkscape to render SVGs, and Inkscape has no command-line option to disable antialiasing.
https://graphicdesign.stackexchange.com/questions/138075/export-svg-without-anti-aliasing-in-inkscape-1-0-by-command-line
You could render at high resolution and then do nearest-neighbour downsampling. It would reduce the visible antialiasing, but you would still get some colours not in the SVG file.
Related
I'm trying to convert and resize eps files into jpg. I use php imagick for this.
After converting the quality is very bad.
my eps you can download here:
https://www.file-upload.net/download-14285439/icon.eps.html
my jpg-img
i use this code:
if ( extension_loaded('imagick') ) {
$imagePath = 'icon.eps';
$imagick = new Imagick();
$imagick->setResolution(300, 300);
$imagick->setColorspace(Imagick::COLORSPACE_SRGB);
$imagick->readImage($imagePath);
$imagick->resizeImage(0, 1000, Imagick::FILTER_LANCZOS, 1);
$imagick->setImageResolution(72, 72);
$imagick->setImageCompressionQuality(70);
$imagick->setImageCompression(\Imagick::COMPRESSION_JPEG);
$imagick->setCompressionQuality(70);
$imagick->setImageFormat('jpeg');
$imagick->writeImage('test.jpg');
} else {
echo 'not found';
}
same result with this settings without resize/only convert, but the quality is still bad:
if ( extension_loaded('imagick') ) {
$imagePath = 'icon.eps';
$imagick = new Imagick();
$imagick->setResolution(300, 300);
$imagick->setColorspace(Imagick::COLORSPACE_SRGB);
$imagick->readImage($imagePath);
$imagick->setImageFormat('jpeg');
$imagick->writeImage('test.jpg');
} else {
echo 'not found';
}
i use this version with php 7.2.33:
phpinfo
What is wrong?
As you obviously know ImageMagick uses Ghostscript to render EPS files to JPEG. I would suggest that, rather than use ImageMagick you use Ghostscript directly. This will give you more control over the process than using ImageMagick and will mean that you can post the Ghostscript command line instead of an IM one.
I'm afraid that I have no idea what ImageMagick sends to Ghostscript which makes it rather difficult to offer any suggestions.
In addition you really need to be much more explicit about your problem. What do you actually mean by 'the quality is very bad'. Is this purely subjective or is there some objective criteria you are using ?
The image you've posted doesn't look much like what I see, but since I don't know what command is being used to drive Ghostscript, it may simply be that I am not reproducing your setup exactly.
First note; the nature of your EPS is not really suitable for JPEG compression. JPEG performs best when applied to smoothly varying images, like photographs (JPEG = Joint Photographic Expert Group), it does not work well with large areas of flat colour with sharp edges (which is exactly what you have here), the high frequency component of the sharp edges gives rise to 'ringing' or 'fringing' effects.
When using Ghostscript directly it is possible to alter the JPEG quality. Setting -dJPEGQ=100 will produce the highest quality, trading off the compression (ie the output file will be larger).
In addition your EPS gives its BoundingBox as 20x20 points. So that's 20/72 inch in each dimension. Even at 300 dpi that's going to result in an image which is 84x84 pixels. Pretty small. At 72 dpi you'll get an image which is 20x20 pixels,
It looks to me like you have rendered the EPS at 72 dpi with the default JPEGQ value, the 'poor quality' appears to be nothing more than the well known artefacts produced by JPEG compression. Using that setup with Ghostscript produces something not entirely unlike your posted image (though without the sharp edged corner artefacts). Setting JPEGQ to 100 produces something more sensible. The file produced by the default settings is 3,564 bytes, while the higher quality file is 4,485 bytes.
If it were me I would render to a TIFF file at a decent resolution, say 1200 dpi to give an image 333x333 pixels. Then load that into ImageMagick and resize it to your desired dimensions. Finally export as a JPEG if you require it that way for some reason.
here's a comparison of the output from Ghostscript. On the left is a JPEG produced at 1200 dpi, in the middle is the default quality rendering at 72 dpi and on the right the 72 dpi rendering with JPEGQ set to 100.
How can I make a screenshot from every page of PDF file and save result as images in PHP? Is it possible?
Maybe the "make a screenshot" can be replaced for your purpose by "create a raster image" for each PDF page?
In this case you could use ImageMagick and/or one of its PHP-enabled libraries. Here is a command line representation:
convert some.pdf[15-19] some.png
This will convert not all pages, but the page range 16--20 (page counting here is zero-based (not intuitive, I know...). To convert all pages, just skip the [15-19] part.
The output PNG names will be some-0.png, some-1.png, ... some-4.png.
To create JPEG or GIF instead of PNG, simply use one of these:
convert some.pdf[15-19] some.jpg
convert some.pdf[15-19] some.gif
By default ImageMagick will use a resolution of 72 PPI. This will indirectly determine the image dimensions of the PNG/JPEG/GIF output. Should you need other output dimensions than the defaults, you have different options, for example:
either add -density
or add -resize
to the command line:
convert -density 200 some.pdf some.png
convert some.pdf -resize 50% some.png
I am trying to add round corners to a jpeg file, but the problem is that after adding round corners, I am getting a black background color. Somehow I am not able to change it to any other color (white, transparent, red). It just simply shows black background where the image has rounded corners.
The code that I am using is:
<?php
$image = new Imagick('example.jpg');
$image->setBackgroundColor("red");
$image->setImageFormat("jpg");
$image->roundCorners(575,575);
$image->writeImage("rounded.jpg");
header('Content-type: image/jpeg');
echo $image;
?>
I cannot use png as the jpeg files are huge, about 5 MB, so if I used png, the file size would go up to 26 MB, even though the png adds transparent round corners.
Also the IMagick version that i am using is:
ImageMagick 6.6.2-10 2010-06-29 Q16 http://www.imagemagick.org
Also the output(image generated) will get printed so I don't know if css will work over here.
Sorry, I am trying to actually create a new jpeg file with rounded corners from an already existing jpeg file that doesn't have round corners this is actually a photograph taken from a camera, so there are multiple/too many colors so I can't use gif as well.
Also my site will only just generate the round corner image then afterwards it will get downloaded using a FTP program by the admin of the site and then using a system software will get printed, so in short my website will not be printing the image but rather just generate it
Try this:
<?php
$input = 'example.jpg';
$size = getimagesize($input);
$background = new Imagick();
$background->newImage($size[0], $size[1], new ImagickPixel('red'));
$image = new Imagick($input);
$image->setImageFormat("png");
$image->roundCorners(575,575);
$image->compositeImage($background, imagick::COMPOSITE_DSTATOP, 0, 0);
$image->writeImage("rounded.jpg");
?>
I may get downvoted, but I say let css deal with the corners and take some load off of your server :)
CSS rounded corners.
JPG doesn't have a transparent color(s) (alpha channels) in its palette.
The output image must use either PNG or GIF (or another image format that supports alpha channels).
setImageBackgroundColor is another option if you want an opaque background.
EDIT
Your comment reminds me that you could try to use the command line; shell_exec() will run a command line argument from PHP. The command in the ImageMagick API you'll need to start with is convert example.jpg, and then you can pass flags with the various parameters you want.
Since ImageMagick is already installed, it will work right away. You may need to point your system PATH to the ImageMagick directory where all of the executables are.
There's plenty of questions and forums dedicated to rounded corners with this method so I'll leave that up to you.
Here's a helpful tip though - there is a silly confusion with the convert command, since Windows also has a convert.exe that is rarely used, but will confuse your command line, so make sure you're calling the right convert. ;) To test if it's working, try convert example.jpg example.gif (which should convert your example to a gif).
To get output from your command line, finish all commands with 2>&1 which will pipe cmd output back into PHP.
I have a PHP application which needs to deal with incoming TIFF files. I have neither control nor knowledge over the colorspaces of this TIFFs and the application should store all incoming images as RGB JPEGs.
Problem is, incoming TIFF files are anything: CMYK, RGB, some sort of YCbCr wrapped in sRGB, and so on, and I need to convert them somehow to RGB JPEGs before saving.
I need some sort of a conversion function in PHP which uses IMagick extension which can get any binary TIFF data and convert it to proper RGB JPEG binary data. It needs to handle different colorspaces inside TIFF images correctly. Output format (RGB JPEG) stays the same for any input file.
The following obvious solution converts some CMYK TIFFs correctly, some CMYK TIFFs get inverted colors and YCbCr RGB TIFFs get totally corrupted by red overlay:
$converter = new IMagick();
$converter->setResourceLimit(6, 1);
$converter->readImageBlob($data);
if ($converter->getImageColorspace() != IMagick::COLORSPACE_RGB
&& $converter->getImageColorspace() != IMagick::COLORSPACE_GRAY
) {
$icc_rgb = file_get_contents('sRGB_v4_ICC_preference.icc');
$converter->profileImage('icc', $icc_rgb);
$converter->setImageColorspace(IMagick::COLORSPACE_RGB);
}
$converter->setImageFormat('jpeg');
$converter->setImageCompression(Imagick::COMPRESSION_JPEG);
$converter->setImageCompressionQuality(60);
$converter->resizeImage(1000, 1000, IMagick::FILTER_LANCZOS, 1, true);
$converter->stripImage();
$result = $converter->getImagesBlob();
This solution is taken from there: http://blog.rodneyrehm.de/archives/4-CMYK-Images-And-Browsers-And-ImageMagick.html Obviously, it doesn't work for all colorspaces, because it doesn't detect them reliably. As you can see, it even uses the sRGB_v4 ICC color profile downloaded from it's homepage.
Google finds me one particular solution to the red overlay problem (just one of the conversion screw-ups), but it's only for console and when you know beforehand that you deal with YCbCr images:
convert some.tif -set colorspace YCbCr -colorspace RGB some.jpg
I can live with passthru-ing convert and pass to convert all the magical switches needed, but I suppose I need to detect the source image's colorspace beforehand and call a identify | grep before every convert in an otherwise PHP application is an overkill.
I've experienced this same issue.
It also came up in the imagick forums and the correction was pushed into ImageMagick 6.8.0-4 .
So upgrading should solve this issue. I've upgraded to ImageMagick 6.8.1-9 and haven't encountered this since.
There's a need to transform .svg files and save em either in .svg or jpeg format. The problems with ImageMagick is that it saves transformed files on white background and I deadly need it on transparent.
Any suggestions with other tools or clear php? Would really appreciate it.
The right ImageMagick command should be:
convert -background none somefile.svg somefile.png
You should use PNG or GIF as file format, because JPEG doesn't support transparency.
To use it in PHP:
<?php
$svg_file_name = "somefile.svg";
$png_file_name = "somefile.png;
system("convert -background none $svg_file_name $png_file_name");
?>
I doubt you can transform SVG files easily from within php. SVG files are basically XML files, and the standard is public, so anyone can make a converter...
I'd go for the external tool, it's easier and faster than processing from within a scripted language, and a lot safer when the author of the script dosen't actually know how to find out the command line switches for an application, and that JPEG files does not support transparency:)
go for convert -background none somefile.svg somefile.png as Jens said...
You can't do transparency with JPEG, but here's how to save an SVG as a PNG with a transparent background...
$image = new Imagick();
$image->setBackgroundColor(new ImagickPixel('transparent'));
$image->readImage('somefile.svg');
// ... do any image manipulation you need to here ...
$image->setImageFormat('png32');
$image->writeImage('somefile.png');