I'm uploading images to my website and optimising them by removing EXIF data using Image Magick's stripImage() function.
$img = new Imagick($image);
$img->stripImage();
$img->writeImage($image);
$img->destroy();
It works quite well, I get reduced file sizes as expected. However, if I open the image in Photoshop, photoshop reads the image as having a resolution of 1 Pixel per Inch.
It seems that stripImage is removing the EXIF data that photoshop uses to determine resolution.
How do I prevent this behaviour while stripping everything else?
The short answer is that I don't think you can selectively remove parts of the EXIF data with ImageMagick, so you will probably need to extract the original density, clear the EXIF, then put back whatever Photoshop needs... not sure though, if Photoshop uses the standard density in a JPEG header or a value from the EXIF data.
Anyway, to work out the answer, you can get all density type settings in an image with EXIFtool like this:
exiftool "-*resolution*" image.jpg
X Resolution : 72
Y Resolution : 72
Resolution Unit : inches
Exiftool is described here. Or, as you know, and love ImageMagick, you can use identify like this:
identify -verbose IMG_3942.JPG | grep -i reso
Resolution: 72x72
exif:ResolutionUnit: 2
exif:thumbnail:ResolutionUnit: 2
exif:thumbnail:XResolution: 72/1
exif:thumbnail:YResolution: 72/1
exif:XResolution: 72/1
exif:YResolution: 72/1
You can also set the density with ImageMagick after you have stripped the EXIF data like this:
# Strip EXIF then add in resolution
convert IMG_3942.JPG -strip -density 180x180 180.jpg
# Check what happened
exiftool "-*resolution*" 180.JPG
Resolution Unit : inches
X Resolution : 180
Y Resolution : 180
You can also modify the EXIF data with libexif if you look here.
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.
I am trying to convert an image with ImageMagick. I am cropping and resampling to 112 DPI:
convert myimg.jpg -crop 1024x683+0+0 -resize 100% -resample 112 downsample.jpg
A script runs through many images of varying DPI and downsamples them.
However, a particular file has gummed up the script. Somehow, the file has a DPI of 1 (?!?) So it ends up trying to sample it up to 112 from 1, and the attempt eats up all my RAM and hangs the script.
identify -verbose myimage.jpg
Image: myimage.jpg
Format: JPEG (Joint Photographic Experts Group JFIF format)
Class: DirectClass
Geometry: 1024x683+0+0
Resolution: 1x1
Print size: 1024x683
Is there an argument/flag I can use with ImageMagick to prevent this from happening, maybe something that tells it to only downsample?
Could your error be related to...
For formats which do not support an image resolution, the original resolution of the image must be specified via -density on the command line prior to specifying the resample resolution.
JPEG I know supports resolution but maybe its wrong in the EXIF header or somehow ambiguous / confused with embedded thumbnail (again, maybe the unit is assumed). I'd look more closely at the [-density] argument (http://www.imagemagick.org/script/command-line-options.php#density) and how it relates to resolution and density on certain formats.
As for getting your script working. Seems you might want to break the operations out into more individual actions? If you can't satisfy the convert with using -density I would look at testing for the case you know fails and just skipping. Could parse the results of identify or just the failure of the convert. You are executing these in shell calls from PHP yes?
The following script is supposed to create an image with lower quality and so smaller file size (kb), instead it create an image with lower quality but bigger file size.
On my test the original is about 300kb, using 90% quality the output is almost the double and using 100% quality, the output is more than 1mb ...
<?php
$quality = 90;
$path = '/var/www/TEST/';
$inputSrc = $path . 'original.jpg';
$outputSrc = $path . 'after' . $quality . '.jpg';
$handler = imagecreatefromjpeg($inputSrc);
imagejpeg($handler, $outputSrc, $quality);
I assume the issue is related to imagejpeg bad implementation ...
is there any way to workaround this ?
isImageMagicka better solution ?
Thanks
Update
I was curious so I gave a try to ImageMagick and unfortunately I have similar result (slightly better).
Full test results:
Original size: 294.6Kb
GD (imagejpeg) 90%: 581.7Kb
GD (imagejpeg) 100%: 1.1Mb
ImageMagick 90%: 431.7Kb
ImageMagick 100%: 780.9kb
Update 2
I did some more test with GIMP and looks that in order to obtain a file with very similar size to the original one you have to check the option use quality setting from original image.
Now I'm confused more ... since when I select that setting Gimp automatically change the output quality to 74% (for the example image).
I was assuming that the JPEG quality value, if lower that 100%, decrease the image quality at every iteration of a save ... but I start to think I'm wrong here.
Update 3
With ImageMagick is not necessary to specify the quality of the sample and if you leave it emptyImageMagick will use the same quality detected in the input image.
So for the example image it is detected as a quality of 69 and the outfile is 326kb. That is the best result so far.
Here the image I'm using:
I had a little look at this. You can work backwards in ImageMagick and, rather than define the quality and see what size results, you can define the size and see what quality results. So, for a concrete example, you can say you want the output file not to exceed 100kB, like this:
convert MShRR.jpg -define jpeg:extent=100k out.jpg
and you get 99kB like this:
-rw-r--r--# 1 mark staff 294608 14 Jan 09:36 MShRR.jpg
-rw-r--r--# 1 mark staff 99989 14 Jan 09:44 out.jpg
To my eyes, the resulting image is a little posterised:
You can often add a tiny amount of blur to disguise this, as follows:
convert MShRR.jpg -blur x0.5 -define jpeg:extent=100k out.jpg
YMMV - Your Mileage May Vary !!!
I am Having PNG Image And Trying To Flop (Mirror) by imagick function of php It Gets Flop Exactly But The
Base Image is In Format 24 Bit RGB
and after Convertion It Gets To
8 Bit Pallated
. So the Main Problem is that when I use to place both images in my pdflib pages one of the image(converted) displays curly....
Original Image
Output After Flop(Mirror) by Imagick and Rendered in PDFlib ->
My Code Is Simple ---->
$im = new Imagick($background_image);
$im->flopImage();
$im->writeimage($background_image."_flop.png");
Modified Date => 29 Oct 2013
Original Image -> Size 4.68 KB Bit Depth 32
Flopped Image -> Size 7.99 KB Bit Depth 64
Automatically Changes It's Properties
ORIGINAL
Converted
Imagick is using the smallest format possible to save the image. Saving in these formats all produce the same image but have the sizes:
Palette - 3.38kB
RGBA 32bit - 6.14kB
RGBA 64bit - 8.09kB
Saving to the smallest possible file is usually what people desire. However you can disable this in a couple of ways.
You can tell Imagick to use the same PNG format as the source image by setting the png:format option to png00. e.g.
$imagick = new Imagick(realpath("../images/FlopOriginal.png"));
$imagick->flopImage();
$imagick->setOption('png:format', 'png00');
$imagick->writeImage("../images/Flop.png");
The full options for png:format are png8, png24, png32, png48, png64, and png00.
Alternatively you can explicitly set the image format to use when saving the PNG file, through the png:bit-depth and png:color-type e.g.
$imagick = new Imagick(realpath("../images/FlopOriginal.png"));
$imagick->flopImage();
$imagick->setOption('png:bit-depth', '8');
$imagick->setOption('png:color-type', 6);
$imagick->writeImage("../images/Flop.png");
The color type values come from the libpng.h and are:
PNG_COLOR_TYPE_GRAY 0
PNG_COLOR_TYPE_RGB 2
PNG_COLOR_TYPE_PALETTE 3
PNG_COLOR_TYPE_GRAY_ALPHA 4
PNG_COLOR_TYPE_RGB_ALPHA 6
Both those methods produce a flopped image that is RGBA 32bit like the original image.
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!