Imagick: EPS to JPG - php

I have an eps. I want to make an jpg out of it. I tried everything, but the quality is too bad.
I think imagick takes the original size of the file, makes an jpg, and then makes it bigger without any compression. The problem is, the generated image of the eps is in bad quality, and the bigger image is totally bad.
Here are some configurations I tried:
$imagick = new \Imagick();
$imagick->readImage($imagePath);
$imagick->flattenImages();
$imagick->resizeImage(1024, 0, \Imagick::FILTER_LANCZOS, 1);
$imagick->setImageResolution(300, 300);
$imagick->setImageCompressionQuality(100);
$imagick->setImageCompression(\Imagick::COMPRESSION_JPEG);
$imagick->setCompressionQuality(100);
$imagick->setImageFormat('jpeg');
$imagick->writeImage($new_imagePath);
Can anyone help me with this? I don't get it.

You'll need to set the image density/resolution before you read the Encapsulated PostScript file.
$imagick = new \Imagick();
$imagick->setResolution(100); // or 300
$imagick->readImage($imagePath);
Also note that, by nature, EPS is a vector format, and JPEG is a lossy raster format. Rendering at a low dpi, and resizing up to a given size will always result in poor quality. Either render at a high-dpi & downsample to a given size, or render at expected size & omit any resizing.

Related

PHP imagick - Convert eps to jpg but poor quality

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.

php copy image increases file size

I am using php to resize and crop images. However the cropped image file is greater than ( much greater in some cases) than the original file. I even tried without cropping (copying the original image) but the resulting size is more than the original image.
$ImageName = '/IMAGES/testImage.jpg';
//Download the Image File
$base_url = 'https://image.jimcdn.com/app/cms/image/transf/none/path/sa6549607c78f5c11/image/ia62ed3191fcc424f/version/1457278719/athens-european-best-destinations.jpg';
$image_size = getimagesize($base_url);
$image_width = $image_size[0];
$image_height = $image_size[1];
$src_image = imagecreatefromjpeg($base_url);
//Copy Image Object To File
imagejpeg($src_image, $ImageName, 100);
Technically, the quality rate of the conversion is not derivable from
the jpeg data, it just tells the converter which tradeoff to make
between size and quality.
Some converters store it in the EXIF data of the JPEG header though,
so if that is still present you can use it with exif_read_data on it,
and see if the compression information is returned.
Source
try to reduce quality and set 80 for example. Quality will be still ok, it's even higher then default quality which should be 75 if you set nothing.
So, put like this:
imagejpeg($src_image, $ImageName, 80);
I think you can try this ImageCopyResampled in this case if you want to keep every pixel like original image. It's slower but better than imagejpeg.
And about quality of image using imagejpeg the quaility property refers to how much jpeg compression you want to apply to the saved or created output image.
0% quality means maximum compression and 100% quality means minimum compression.
The more compression you apply, the smaller the output filesize will be relative to the original uncompressed filesize.
Just exclude the image quality parameter:
imagejpeg($src_image, $ImageName);
GD will automatically create a smaller image for you

Convert vector to raster in php

I am trying to convert a vector image formats .emf,.wmf to a high resolution sharp and crisp raster image .gif,jpg. (Usually this could be easily done in Illustrator). But i am unable to do this in PHP. I am trying the following code but the results are either blurry or distorted or even totally black.
<?php
$image = new Imagick("1.emf");
$image->resizeImage(1500,0,Imagick::FILTER_LANCZOS,1);
$image->setImageFormat('gif');
$image->setresolution(900, 900);
$image->writeImage("2.gif");
?>
We just needed to set the resolution before loading the image.
$image = new Imagick();
$image->setresolution(300, 300);
$image->readimage($filename);
$image->resizeImage(1500,0,Imagick::FILTER_LANCZOS,1);
$image->setImageFormat('jpg');
$image->writeImage("1.jpg");
This code will convert a vector to a sharp and crisp raster image. It works for all vector formats (svg, ai, emf, wmf, etc). If the jpg result is unexpectedly a black image, you need to change the image transparency to white (check this link). Another way to get around with transparency problem is by getting your PHP updated to 5.5 and by installing Imagick for that version. By doing so, it will not cause any problems with transparent images and the above code will just work fine.
For testing purposes you could change jpg to png because it supports transparency.

Partial black background when watermarking PNG image with GD PHP

I have pieced together a PHP class to perform various image related functions using GD functions of PHP.
It works great for all image types. Rotate, flip, resize, crop and to a lesser extent, watermark.
All but the latter work perfectly. For example after a few changes, rotated PNG images retained their transparency whereas before they were losing that and the background turning black. Common problem, it appears. But all working now.
Where I'm still getting stuck is watermarking a PNG image with another PNG image. It appears to work fine with JPG and other images. This is the code (simplified):
public function writeWatermarkSimple()
{
$watermarkFile = 'watermark.png';
$watermarkImage = imagecreatefrompng($watermarkFile);
imagealphablending($watermarkImage, false);
imagesavealpha($watermarkImage, true);
$imageFile = 'image.png';
$baseImage = imagecreatefrompng($imageFile);
imagealphablending($baseImage, false);
imagesavealpha($baseImage, true);
$marginH = imagesx($baseImage) - imagesx($watermarkImage);
$marginV = imagesy($baseImage) - imagesy($watermarkImage);
$cut = imagecreatetruecolor(imagesx($watermarkImage), imagesy($watermarkImage));
imagecopy($cut, $baseImage, 0, 0, $marginH, $marginV, imagesx($watermarkImage), imagesy($watermarkImage));
imagecopy($cut, $watermarkImage, 0, 0, 0, 0, imagesx($watermarkImage), imagesy($watermarkImage));
imagecopymerge($baseImage, $cut, $marginH, $marginV, 0, 0, imagesx($watermarkImage), imagesy($watermarkImage), 80);
if (!imagepng($baseImage, 'watermarked_image.png'))
{
return false;
}
return true;
}
This has been pieced together with various guides and advice people have given based on a similar issue. Again, working perfectly with JPG images and PNG watermarks, but not PNG & PNG.
Some example images:
http://i.imgur.com/hHRWinj.png - This is the watermark I'm using.
http://i.imgur.com/6sy8Ncs.png - This is the image I'm applying the watermark to.
http://i.imgur.com/ghovYLm.png - This is the end result.
The bit I find interesting is that any part of the watermark that is overlaid on a non-transparent portion of the image is working fine. Just the rest of it has the black background.
This leads me to believe I'm close, and I hope that the expertise of you fine people may lead me to the solution.
Thanks ever so for reading.
So, I'm not giving up on finding the correct answer to do this using GD. However, I was overjoyed to find that what needed up to 30 lines of code with GD can be achieved using much less with ImageMagick:
$image = new Imagick();
$image->readimage($this->_image);
$watermark = new Imagick();
$watermark->readimage($this->_watermark->_getImage());
$watermark->evaluateImage(Imagick::EVALUATE_DIVIDE, 2, Imagick::CHANNEL_ALPHA);
$image->compositeImage($watermark, imagick::COMPOSITE_OVER, $marginH, $marginV);
So this is before (with GD):
http://i.imgur.com/AlS0TcO.png
And after (with ImageMagick and the code above):
http://i.imgur.com/zBxlC3R.png
If anyone has an answer that is purely GD then I'd be immensely grateful.
Ran into some similar issues recently and while this may not exactly solve your problem, these were some useful discoveries that I made.
In my case, I have an original .jpg image and a watermark .png image. The watermark image has a fully transparent background. I wanted to specify the opacity in my script and have it change the watermark opacity before placing it on top of the origina image. Most posts out there regarding PHP watermarking assume that the original watermark .png file already has the solid watermark portion set to the correct opacity rather than changing it via the script.
gd didn't like a 24 bit .png and caused some goofy issues. Switching to 8 bit resolved that with gd. On the other hand, imagick works very well with a 24 bit .png and the final result seems to be better.
For me, using gd worked just fine if I was opening the original watermark .png and using imagecopymerge() to set the watermark transparency. If however I tried to scale the original watermark .png (which has transparent background) first, then I would get similar results as you with black or white background portion of where watermark image is. See How do I resize pngs with transparency in PHP? for a partial solution by filling the new wm image with transparent rectangle first. For me this still produced an opaque white background on the final result no matter what I tried.
I switched to imagick and was using setImageOpacity() to change the transparency of my watermark .png before applying it on top of my original image and I was still getting the same effect with a black background. Finally read in the PHP doc for setImageOpacity() that if the original .png has any transparent pixels and you try to lower the opacity, those pixels become opaque (black) with the new transparency applied. Instead, need to use the evaluateImage() function. This will instead evaluate each pixel's alpha channel only and divide by the specifid number.
I assume the black / white background issue with gd is likely due to similar ways that it treats alpha channels when scaling / combining as compared to imagick and if you want to do it all in gd you just need to find some similar way to evaluate and manipulate the alpha channel per-pixel because the "easy" ways seem to take an already transparent background and make it opaque.
So, the solution:
Assuming you want to apply your watermark at an opacity of 45% and you're using imagick, then instead of this:
$watermark->setImageOpacity(.45);
do this
$watermark->evaluateImage(Imagick::EVALUATE_DIVIDE, (1/.45), Imagick::CHANNEL_ALPHA);
You need to divide 1 by your opacity to get the demoninator by which the function will divide the alpha channel value for each pixel. In this case, 1/.45 = 2.2222, so then the function will divide the alpha channel of each pixel by 2.2222. This means a solid pixel (alpha of 1) would result in 1/2.2222 or .45 alpha or transparency when finished. Any pixels that were already transparent (alpha 0) would stay transparent because 0 divided by anything is always what? Zero!
After you change the watermark transparency then you can use compositeImage() to merge the watermark onto the original image.

PHP+Imagick - PNG Compression

How do I efficiently compress a PNG? In my case, the images are small grayscale images with transparency.
Currently I'm playing with this:
// ...
$im->setImageFormat('png');
$im->setImageColorspace(\Imagick::COLORSPACE_GRAY);
$im->setImageCompression(\Imagick::COMPRESSION_LZW);
$im->setImageCompressionQuality(9);
$im->stripImage();
$im->writeImage($url_t);
As Imagick doesn't offer COMPRESSION_PNG, I've tried LZW but there's almost no change in the filesize (usually it's even bigger than before).
If I open the image in GIMP and simply save it, the filesize gets drastically reduced (e.g. 11,341 B --> 3,763 B or 11,057 B --> 3,538).
What is the correct way of saving a compressed PNG with Imagick?
Have a look at the first part of this answer:
Convert multipage PDF to PNG and back (Linux)
It explains the meaning + syntax of ImageMagick's -quality setting for PNGs.
I'm definitely not sure if it is correct way to save PNG, but my way is:
$im->setImageCompression(\Imagick::COMPRESSION_UNDEFINED);
$im->setImageCompressionQuality(0);
This gives me perfect quality of the image and file size very similar to PS6 saved 'Save for Web'. Sometimes even smaller sizes!

Categories