GD imagejpeg() compression? - php

I'm working on a project where I edit the pixels of a jpg in PHP using the GD library.
Its very crucial and key to my project that the output from PHP retains the pixel values I set (cough-steganography-cough).
This is the first time I've attempted image manipulation in PHP. I've had no problems before in my Java implementations, so I was foolish not to investigate GD's jpeg compression quality before pursuing further.
It turns out that after all my effort, my code does not function the way its supposed to. I am pretty sure it is not my code (tested the encode and decode functions on edited image resources and they worked).
My questions are:
The only problem I can see is with imagejpeg()'s compression. Could I be right?
Are there any libraries that provide the compression that I need?(retain pixel values that I changed)

By default the quality of the image output from imagejpeg is 75, Try setting it at 100 to get the image at full quality.
bool imagejpeg ( resource $image [, string $filename [, int $quality ]] )
Check the manual for further details.
Also try using imagecopyresampled. (I think you would have been using imagecopyresized somewhere in your code. Use imagecopyresampled instead of it. )
EDIT
Then I think you should try ImageMagick(or GD2). It gives a better quality than GD . Check this

The JPEG file format is not very suitable for steganography if you do the steganography pixel by pixel.
JPEG uses an image compression - that even with maximum quality - that will destroy the information on the bit level on each pixel. The jpeg type of compression (lossy compression) is made for the human eye/brain to retain the image but not the bits of the image in the file .
You need to use an image format that is capable to retain the pixels - as you wrote it already as well. Such a format more likely is BMP with RLE compression or the TIFF image format with ZIP or RLE compression. That's called lossless data compression.

Use the imagepng() instead of the imagejpeg() function and set the compression to 0 :
bool imagepng ( resource $image [, string $filename [, int $quality [, int $filters ]]] )
See : http://php.net/manual/en/function.imagepng.php

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

How efficient is a PHP image resource?

I have a very large PNG image, and I am writing a method to get the value for a color at a specific (but changing) pixel of that image. When I create the image using:
$image = imagecreatefrompng('map.png');
Is the whole image loaded into memory (not ideal), or does it just read the meta data and prepare for other calls so that when I call:
int imagecolorat ( resource $image , int $x , int $y )
Will it file seek to the right pixel or pull from memory? If I'm trying to optimize this routine to be called repeatedly, would I be better off converting the image data I need into some raw binary format and using file seek? I'd like to avoid repeatedly loading the whole file into memory if possible.
You need a big php memory to play with php image resources.
Use graphicsMagick instead. http://www.graphicsmagick.org/

php reverse imagecreatefromstring

Is there a way to turn a jpg to string, reverse of imagecreatefromstring?
I have to communicate to a server which needs binary of image, i saw plenty of jpg to binary but not the other way around.
Just a shot in the dark here... No real experience with this, just my thoughts after looking through some documentation...
I see in the documentation of imagecreatefromstring() an example is given where a base64 encoded string is converted into an image. Taking that example and flipping it around might just be what you are looking for.
$image = file_get_contents('image_file.jpg');
$imageString = base64_encode($image);
imagecreatefromstring takes a string which contains the binary data of an image and turns it into a gd image resource so you can manipulate it with the gd image library. Literally the "reverse" of that would be imagejpeg, which saves a gd image resource to a jpeg image.
I guess what you really want though is simply the initial string, which contains the binary data of the image to begin with. I.e.:
$imageString = file_get_contents('image.jpg');
$gd = imagecreatefromstring($imageString);
Just skip step 2.

How to reduce file size using PHP and JPEGs

I am using a the standard PHP functions imagecopytruecolor and imagejpeg
to rescale and produce uploaded images from a standard HTML form. The images appear at the correct size however the image filesize is quite high (e.g. 540px * 350px = 250kb)
When compared to Photoshop's Save for Web using JPEG high quality settings the same files are come out at about 60kb, so about 4 times as small.
Is there anything I can do to reduce the filesize?
You can set $qualityin imageJPEG. From the manual:
bool imagejpeg ( resource $image [, string $filename [, int $quality ]] )
quality is optional, and ranges from 0 (worst quality, smaller file) to 100 (best quality, biggest file). The default is the default IJG quality value (about 75).
In my experience, it is not advisable to go much under 70%, though.
You may want to try whether you can get better results with smaller file sizes from other image processing engines like ImageMagick, if you can use that. I often have the feeling that GD's JPG encoder is not top of the line, but that's nothing more than a subjective impression at the moment.
No image library I've ever seen comes anywhere close to how efficiently Photoshop compresses a file. You could try using another library like ImageMagick (aka Imagick) which might saves smaller files at the same quality size than the default stuff your using, but keep in mind you'll never get a 60K image from these libraries at this res.
You can change the quality setting (3rd argument of imagejpeg, see the docs). The default is only 75% though, which should already be rather small.
From the docs
bool imagejpeg ( resource $image [, string $filename [, int $quality ]] )
experiment with $quality

Categories