how to restore the watermark set with Imagick::steganoImage() - php

So I used this Imagemagick library wrapper written in PHP and came to know about this function called steganoImage() which simply says that it will hide a watermark inside the image. But problem is documentation doesn't state how to restore that image back. I checked all the other functions too, didn't find anything. I would like to have an Imagick solution for this.

Before you spend to much time on this you need the original dimension you used to create the secret image to retrieve it. So if the image is cropped, resized or format changed you probably will not be able to retrieve the message.
For your information this is a good site for Imagick examples: https://phpimagick.com/Imagick/queryFormats Although they do not mention steganoImage()
Looking on the web I found the code below ( Codesearch ) which adapted should work for IMagick:
#!/usr/bin/perl
use Image::Magick;
#
# Hide an image within an image
#
$watermark=Image::Magick->new;
$watermark->ReadImage('smile.gif');
($width, $height)=$watermark->Get('width','height');
#
# Hide image in image.
#
$image=Image::Magick->new;
$image->ReadImage('model.gif');
$image->SteganoImage(image=>$watermark,offset=>91);
$image->Write('model.png');
$image->Write('win:');
#
# Extract image from image.
#
$size="$width" . "x" . "$height" . "+91";
$stegano=Image::Magick->new(size=>$size);
$stegano->ReadImage('stegano:model.png');
$stegano->Write('stegano.gif');
$stegano->Write('win:');

The answer provided by Bonzo is correct. An example in PHP's Imagick would look very similar.
$image = new Imagick('rose:');
$watermark = new Imagick('label:Hello World!');
// The decoding process must "know" about the watermarks size, and starting
// pixel offset.
define('STEGANO_OFFSET', 64); // Secret offset
define('STEGANO_WIDTH', $watermark->getImageWidth());
define('STEGANO_HEIGHT', $watermark->getImageHeight());
$stegano = $image->steganoImage($watermark, STEGANO_OFFSET);
$stegano->writeImage('output.png');
To decode the original watermark, define the width, height, and offset of the hidden image before reading the file.
$decoded = new Imagick();
$decoded->setSizeOffset(STEGANO_WIDTH, STEGANO_HEIGHT, STEGANO_OFFSET);
$decoded->readImage('STEGANO:output.png');
$decoded->writeImage('decoded.png');

Related

Save image on RAM and work on it using ImageMagick

I am working on a project where the client can create dynamic image by merging different layers (images) into single image and then show that generated image to client. Currently my code is something like this
$output = uniqid().'.jpg';
exec('convert -size 600x800 xc:white '.$output);
$layers = array(//array of about hundreds of PNG images);
foreach($layers as $key => $singleLayer)
{
$layerIs = $singleLayer['image'];
$positionsXY = explode(',', $singleLayer['xy']);
exec('composite -geometry +'.$positionsXY[0].'+'.$positionsXY[1].' '.$layerIs.' '.$output.' '.$output);
}
$base64 = base64_encode(file_get_contents($output));
unlink($output);
return 'data:image/jpeg;base64,'.$base64;
In my above code, I am generating a white background image and then merging multiple PNG images on it these images are more than 100. While also saving this image every time a single layer is merged and then output the final image to client after deleting the generated image. This all takes about 15 seconds to do.
So, My Question is if ImageMagick has an option which can allow me to save image on ram instead of saving image on harddisk which in turn can speed up my processing?
Although I found this http://www.imagemagick.org/discourse-server/viewtopic.php?t=20295 but could not understand much of it that how can I implement it.
The easiest way to use ImageMagick in php is to use the ImageMagick extension & class. I would not recommend using the exec function for it.
So first off, converting the image and store it in a variable.
You say you are not used to variabled, but by your code it seems like you are, you might just not know it.
For example, your $output is a variabe. The variable contains the image after the output is made (if it succeeds).
Now, I'm not 100% sure what your layers array contains, if its images or paths to images, but I expect that its paths, so I'll go with that assumption.
Your first exec call does a convert, I don't think that is nessesery, cause you have no input, all you need is a "white image" from what I can see.
To do that, create a new image object with and create a new image which is the correct size and bg color:
$image = new Imagick();
$image->newImage(600, 800, "white");
You then loop through the layers as you do, but instead of exec you use the imagemagick image you created above:
foreach($layers as $key => $singleLayer) {
$layerIs = $singleLayer['image'];
$positionsXY = explode(',', $singleLayer['xy']);
// Each loop should load the image into a new imagemagick object, but we release it when the scope is exited.
$layer = new IMagick($layerIs);
$image->compositeImage($layer, Imagick::COMPOSITE_DEFAULT, $positionsXY[0], $positionsXY[1]);
}
When the loop is complete, the $image variable will contain the composited image, which you can return as you wish.
$image->setImageFormat('jpg');
return "data:image/jpeg;base64,{base64_encode($image)}";
Note: Code is not tested and written directly in browser. So it might need to be rewritten!

php imagick won't save PNG compressed but shows compressed in browser

I have the following code in PHP to take the screenshot of first page of the PDF.
$name = getcwd()."\\testfile";
$img = new imagick();
$img->setResolution(200,200);
$img->readImage($name.'.pdf[0]');
$img->setImageResolution(100,100);
$img->resampleImage(100,100,imagick::FILTER_LANCZOS,1);
$img->setImageCompression(\Imagick::COMPRESSION_ZIP );
$img->setImageCompressionQuality('0');
$img->setImageFormat('png8');
$img->writeImage($name.".png");
header("Content-type : image/png");
echo $img;
This code produces the PNG of 62kb only in the Google Chrome's Resource monitor tab. But the image which is written by Imagick() is above 114kb. Just to make sure image isn't compressed and or any other issues i have used a online service called TinyPNG and they compressed the image shrinking it to exactly 62kb i get in browser...
What could be wrong in this code? Also i am using PNG8 format because thats more efficient.
Best
Ahsan
I think this is caused by your writeImage statement. If you write a PNG image without specifying png8: specifically in the filename your image will not be stored in that format. In essence setImageFormat will only affect when you retrieve the image as a string (echo $img).
If you do the following:
$img->writeImage ('png8:' . $name . ".png");
it should be stored as a png8. You can verify this with identify -verbose and checking the Depth / Channel Depth.
These are the default compression methods used for the following common image formats:
PNG: Imagick::COMPRESSION_ZIP
JPEG: Imagick::COMPRESSION_JPEG
GIF: Imagick::COMPRESSION_LZW

Resize a PHP GD-generated image in PHP and display it

I am making an avatar script from scratch and am having some problems. I got transparency working, and multi-image support for heads, bodies, shirts, etc.
Anyhow, I want to be able to generate specific sizes of the avatar within the PHP script. At this time, I have the variable $baseImage, which is an image generated using the GD script below:
$baseImage = imagecreatefrompng($startAsset);
imagealphablending($baseImage, true);
imagesavealpha($baseImage, true);
... combine all images into $base here
header("Content-type: image/png");
imagepng($baseImage);
The size of the image this generates is 350x550 (pixels) and I want to be able to get a smaller size.
I've done research but cannot find a working solution. What built-in PHP GD functions can resize this, retain transparency, and keep the great quality/colors?
There is no way to change the size of an image resource directly. Instead, you need to create a new image of the desired size and use imagecopyresampled to copy from the fullsize image to the resized one.

php image manipulation - fade to transparency

does anyone know how to apply fade effect to an image using PHP ? what I am looking for is a way to apply gradient transparency ( i mean : at the top , the image is opaque , which gradually gets more and more transparent , and at the bottom it is completely transparent).
i have been reading up on http://php.net/manual/en/function.imagecolortransparent.php , but did not see anything about applying a gradient effect to an image.
i also read : PHP - Generate transparency (or opacity) gradient using image , but it kinda trailed off without any solution!
I am also open to any other suggestion / libraries that can do this from command line.
Obviously you'll need to work with a png for this effect, but you can convert any png into a jpg using php. The following question I believe covers what you are asking about. Part of the code will have to be removed to clear the image reflection effect.
Can You Get a Transparent Gradient using PHP ImageMagick?
The piece of code which seems to do what you are trying to accomplish is:
$im = new Imagick('image.jpg'); //Reference image location
if (!$im->getImageAlphaChannel()) {
$im->setImageAlphaChannel(Imagick::ALPHACHANNEL_SET);
}
$refl = $im->clone();
$refl->flipImage();
$gradient = new Imagick();
$gradient->newPseudoImage($refl->getImageWidth() + 10, $refl->getImageHeight() + 10, "gradient:transparent-black");

Using a transparent PNG as a clip mask

Is it possible to take this image:
And apply this mask:
And turn it into this:
Using either GD or Imagick? I know it's possible to mask an image using shapes but I'm not sure how to go on about doing it with a pre-created alphatransparent image. :s
Using Imagick and ImageMagick version > 6 (I don't know if it will work on older versions):
// Set image path
$path = '/path/to/your/images/';
// Create new objects from png's
$dude = new Imagick($path . 'dude.png');
$mask = new Imagick($path . 'dudemask.png');
// IMPORTANT! Must activate the opacity channel
// See: http://www.php.net/manual/en/function.imagick-setimagematte.php
$dude->setImageMatte(1);
// Create composite of two images using DSTIN
// See: http://www.imagemagick.org/Usage/compose/#dstin
$dude->compositeImage($mask, Imagick::COMPOSITE_DSTIN, 0, 0);
// Write image to a file.
$dude->writeImage($path . 'newimage.png');
// And/or output image directly to browser
header("Content-Type: image/png");
echo $dude;
I think you are looking for imagealphablending. I use it for watermarks, and I believe it will do the effect you are looking for.
Great work with (ImageMagick) NOT GD .. I see the tags of this question is GD!!
Here is a GD version at this link:
PHP GD Use one image to mask another image, including transparency

Categories