Imagick convert CMYK JPG to PNG and transparency - php

I have a CMYK JPG file which I need to cut some parts from and then save into a CMYK PNG file. The problem is that even I just open the JPG file and save it into a PNG file the colors are shifted massively. I've been trying to fix that for a day now and have exhausted all available resources on SO and Google.
Here's my code:
$imageStick = new Imagick("original.jpg"); // CMYK JPG
$largeStick = new Imagick(); // create a bigger PNG file with transparent background
$largeStick->newImage($smallStick->getimagewidth(), $smallStick->getimageheight() * 3, new ImagickPixel('transparent'), 'png');
$largeStick->compositeimage($smallStick, Imagick::COMPOSITE_DEFAULT, 0, 0);
$largeStick->writeimage("resampled.png");
And here are the images:
- Original - Download File
- Resampled
Any ideas why would that be happening?
I've tried copying all possible profiles and image properties from the original jpg file:
foreach ($smallStick->getimageprofiles() as $name => $profile)
!empty($profile) && $largeStick->setimageprofile($name, $profile);
foreach ($smallStick->getimageproperties() as $name => $property)
!empty($profile) && $largeStick->setimageproperty($name, $property);
$largeStick->setcolorspace($smallStick->getcolorspace());
manually setting up an ICC profile but no luck at all:
$icc_cmyk = file_get_contents('USWebUncoated.icc');
$largeStick->profileImage('icc', $icc_cmyk);
Any thoughts on this would be highly appreciated!
Thanks!

Related

imagick PHP: image.PNG convert to image.JPG and convert XML/XMP to EXIF.(?)

PNG including metadata -> JPG including metadata
i have a working imagemagick part that converts PNG to JPG.
And instead of XMP-data i need to have title and keywords stored as EXIF.
(ImageMagick 6.9)
$image = new Imagick($img_sourse);
$profiles = $image->getImageProfiles("icc", true);
$image->setImageFormat( "JPG" );
$image->profileImage("icc", $profiles['icc']);
$image->writeImage($save_to);
$image->destroy();

Set background colour in PHP Imagick montage function

I am composing an image from 6 images using this code:
$imagick = new Imagick();
foreach ( $productImages as $productImage ) {
$imagick->addImage(new Imagick($productImage));
}
$categoryCollage = $imagick->montageImage(
$categoryImage,
"3x2+0+0",
"150x100+2+2",
Imagick::MONTAGEMODE_CONCATENATE,
"1x1+2+2"
);
Below the result when images with different size and ratio are added. The background colour is grey. How to set it to white?
According to the manual with the command line version it would be the -background parameter but I don't know how to set it in PHP:
https://legacy.imagemagick.org/Usage/montage/
I found a very trivial solution where the grey background disappears:
foreach ( $productImages as $productImage ) {
$subImage = new Imagick($productImage);
$subImage->resizeImage(150, 100, Imagick::FILTER_BOX, 1);
$imagick->addImage($subImage);
}
I just resize the image to the size which will be then anyway used in the collage and as each original image is bigger, there is no an up-scaling issue.
Using then the Imagick::MONTAGEMODE_FRAME constant it looks then quite OK.

How to crop image with dimensions (without quality loss) in PHP?

I need to crop the image with PHP by using the dimensions.
And save it into the local with JPEG format.
Dimensions that i receive is,
{"left":82.5,"top":48.875,"width":660,"height":371.25}
I need to crop from Original size of the image.
Ex. image is 1200x800, then the result image dimension from the actual size, not resizing or any. Because the quality should be same.
How could i use these params to crop the image ?
Is it possible ?
Use the built-in imagick class:
$image = realpath("/path/to/your/image.extension");
$cropped = realpath("/path/to/your/output/image.png");
$imObj = new Imagick();
$imObj->cropImage($width, $height, $offset_x, $offset_y);
$imObj->setImageFormat("png"); // this is unnesesary, you can force an image format with the extension of the output filename.
$imObj->writeImage($cropped);
As for lossless output, use an image format with lossless encoding. PNG is perfect for the job, since it was designed for network transfer (hence the "Adam-7" interlacing).
Check this related question about lossless image formats on graphic design stack:
What are lossless image formats?
You can use imageCopyResampled function which was designed pretty much exactly for this.
$image = imagecreatefromjpeg($imageFileURL);
/***
* resize values (imported)
***/
$left = 82;
$top = 49;
$width = 660;
$height = 371;
/***
* Create destination image
***/
$newImage = imagecreatetruecolor($width,$height);
$saveToFile = "destintion filespace of image file.jpg"
if(imagecopyresampled($newImage, $image, //dest/source images
0, 0, // dest coordinates
$left, $top, // source coordinates
$width, $height, // size of area to paste to
$width, $height // size of area to copy from
)){
imagejpeg($newImage,$saveToFile,100); //zero compression saved to file
print "image resized ok!!";
}
The new fileimage will be the size specified with $width,$height and will be offset from the original image by the values given in $left and $top. From your question this looks like what you want. This will not resize or change the compression of the image (until you save the file and then possibly set these details yourself).

Imagick jpg background isn't transparent on rotate

I'm currently using imagemagick version ImageMagick 6.8.4-6 2013-04-04 Q16
with Imagick extension version 1620
I am trying to rotate a jpg image and merge this into another jpg image however when i merge the image i get a black box arround the image.
Please see the code i am using below:
public function image($images,$x,$y,$angle){
if($images != "" && $images != NULL){
$base = $this->instance;
$layer = new Imagick($images);
//resize image
if($this->id == 45){
$layer->scaleImage(329,0);
}
if($this->id == 44){
$layer->scaleImage(280,0);
}
if($this->id == 42){
$layer->scaleImage(350,0);
}
//rotate image
$layer->rotateImage(new ImagickPixel("none"), $angle);
//Merge Image
if($this->id == 44){
$base->compositeImage($layer, imagick::COMPOSITE_OVER, $x, $y);
}else{
$base->compositeImage($layer, imagick::COMPOSITE_DEFAULT, $x, $y);
}
$this->image = $base;
}
}
The the test is currently been run when $this->id uses 44.
Can anyone shed light on this issue?
Thanks in advance
You need to use imagecolortransparent in order to have transparency capabilities.
N.B. JPG does not have transparent properties, only PNG and GIF files (and TIFF) but browsers do not support that format.
Your output file will need to be converted to one of those formats, preferably PNG then set the transparency for the desired color.
"so would you suggest converting to PNG then rotating? then merging the PNG image into the JPG (if it is possible) as the image output is required to be a jpg"
You will lose transparency as soon as you resave as JPG
I came across this via Google, here's the correct answer as others may find it. You need to use setImageMatte(1) to enable the transparency, e.g.
$src->setImageMatte(1);
$mask->rotateImage(new ImagickPixel('#00000000'), 10);
You may also use an image Mask, where black will become transparent using
$src->compositeImage($mask, Imagick::COMPOSITE_DSTIN, 0, 0, Imagick::CHANNEL_ALPHA);

PHP GD Image Library change image color - gif works but jpegs wont

Thanks for taking the time to read my problem:
I'm using the following code to get an image and then change the color 201,2,255 (r,g,b) - which is a shade of purple then output the image.
$imgname = "input.gif";
$im = imagecreatefromgif ($imgname);
$index = imagecolorclosest ( $im, 201,2,255 ); // get White COlor
imagecolorset($im,$index,60,140,48); // SET NEW COLOR
$imgname = "output.gif";
imagegif($im, $imgname ); // save image as gif
imagedestroy($im);
This works perfectly which can be seen here : http://www.office-desks.co.uk/cache_images/test.php (top 2 images)
The problem is when I try todo exactly the same but using a jpeg instead it doesn't work.. (bottom 2 images)
$imgname = "input.jpg";
$im = imagecreatefromjpeg ($imgname);
$index = imagecolorclosest ( $im, 201,2,255 ); // get pink/purple COlor
imagecolorset($im,$index,60,140,48); // SET NEW DECENT COLOR
$imgname = "output.jpg";
imagejpeg($im, $imgname ); // save image as gif
imagedestroy($im);
If anyone could help me shed some light on the problem, would be much appreciated. Thanks in advance all.
A bit late, but I think that has to do with the 'artifacts' (compression errors) generated by JPG. Zoom in on a JPG and you see 'grains' of pixels that won't match the neighbors. This means big planes of a single color will become many colors and not 1 single value.
Stick with lossless image formats like gif or png.

Categories