How to make tiled image frame without using exec function? - php

Original image:
Here what i need:
It should be created from this small tile:
A lot of people suggest to use ImageMagick solution (it using php exec function) - http://www.imagemagick.org/discourse-server/viewtopic.php?f=1&t=21867:
convert frame_template.gif \
-tile blackthin_top.gif -draw 'color 1,0 floodfill' -rotate 90 \
-tile blackthin_btm.gif -draw 'color 1,0 floodfill' -rotate 90 \
-tile blackthin_top.gif -draw 'color 1,0 floodfill' -rotate 90 \
-tile blackthin_btm.gif -draw 'color 1,0 floodfill' -rotate 90 \
-gravity center thumbnail.gif -composite frame_filled.gif
or
PICFrame solution (it using php exec function) - http://www.fmwconcepts.com/imagemagick/picframe/index.php:
picframe [-f frameid] [-m mattesize] [-c mattecolor] [-b bordersize] [-s shade] [-a adjust] [-o opacity ] [-d distance] infile outfile
PHP imagick has great ability to create color borders with:
$imagick = new \Imagick('image.jpg');
$imagick->scaleImage(300, 300, false);
// Create frame placeholder
$imagick->frameimage( 'red','30','30', 30, 0);
// Flood fill with color
$imagick->floodFillPaintImage('green', 10, '#6e0000',0, 0,false
);
header("Content-Type: image/jpg");
echo $imagick->getImageBlob();
But PHP imagick can't use your own image tile to create frame, only solid colors. Here is very related question - How to flood fill the frame with a pattern image using imagick php class?
Another good solution from - https://stackoverflow.com/a/28778953/2337706 but it creates image from big PNG frames and you should know correct image size.
I know that i can create it with php GD - http://php.net/manual/en/ref.image.php but i don't know correct way how implement it this way.

In ImageMagick, you could just do something simple like this:
convert a1Wit.jpg -mattecolor black -frame 10x10+3+3 -gravity west -chop 3x0 -bordercolor gold -border 3 frame_result.jpg
These commands should be easy enough to translate into Imagick. See http://us3.php.net/manual/en/imagick.frameimage.php and http://us3.php.net/manual/en/imagick.chopimage.php and http://us3.php.net/manual/en/imagick.borderimage.php
Or simply:
convert a1Wit.jpg -bordercolor black -border 7 -bordercolor "gray(35%)" -border 3 -bordercolor "#D0A456" -border 3 frame_result2.jpg
Or
convert a1Wit.jpg -mattecolor "gray(30%)" -frame 13x13+5+5 -gravity northwest -shave 5x5 -bordercolor "#D0A456" -border 3 frame_result3.jpg
Or
convert a1Wit.jpg -mattecolor "gray(30%)" -frame 13x13+5+5 -gravity northwest -bordercolor "#D0A456" -border 3 frame_result4.jpg
Adjust the color thicknesses as desired

Related

imagemagick trim the bottom from transparent PNG

I am attempting to write an imagemagick command to trim the transparent pixels from the bottom of a transparent PNG. I found these commands and modified them to take off just the bottom. However the output is not as expected.
With some trial and error I've identified that the command appears to be generating an image of a minimum height. If the design is too high it leaves transparent pixels underneath. But nothing jumps out at me as being the element of the command that causes that?
I've included my 3 files that I trimmed and the 3 results that the following command(s)
generates:
convert \( ORIGINAL.png -bordercolor none -border 1x0 \) -size 1x1 xc:black -gravity west -composite -size 1x1 xc:black -gravity east -composite -size 1x1 xc:black -gravity north -composite -fuzz 10% -trim +repage -bordercolor white -shave 1x0 TRIMMED.png
convert \( ORIGINAL2.png -bordercolor none -border 1x0 \) -size 1x1 xc:black -gravity west -composite -size 1x1 xc:black -gravity east -composite -size 1x1 xc:black -gravity north -composite -fuzz 10% -trim +repage -bordercolor white -shave 1x0 TRIMMED2.png
convert \( ORIGINAL3.png -bordercolor none -border 1x0 \) -size 1x1 xc:black -gravity west -composite -size 1x1 xc:black -gravity east -composite -size 1x1 xc:black -gravity north -composite -fuzz 10% -trim +repage -bordercolor white -shave 1x0 TRIMMED3.png
If someone could please explain what I am missing in terms of this height issue that would be really appreciated.
These are the 3 ORIGINAL files and the 3 outcomes showing how the outcome changes with the original file changes.
This is what I am trying to acheive - delete the empty space from the bottom of the image. I want no space after the image at the moment if it is too high I still get space underneath (see the last outcome, bottom right)
---- BELOW ARE JUST THE ORIGINAL FILES IF ANYONE WANTED TO TRY IT ON THEIR SETUP ETC ----
If you're trying to remove what a "-trim" would remove, but only from the bottom edge of an image, this command should give you that result...
convert input.png -background none -set page %[#] \
-set option:distort:viewport %[w]x%[fx:page.y+page.height] \
+repage -distort SRT 0 result.png
It starts by setting some variables that contain the results of a "-trim" operation, but without actually removing anything. Then it uses those variables to calculate the after-trim dimensions for the output viewport. Then it uses a no-op "-distort" to effectively crop the image to the calculated output dimensions, removing only the excess transparent pixels toward the bottom.

How to fill the closed regions by a border color when outlining a transparent image using Imagick PHP

I'd like to outline an object in a transparent background with a 20px border. But, I want to fill in the closed regions with the border color.
$image = new Imagick('./img/hinata.png');
$mask = clone $image;
$mask->separateImageChannel(Imagick::CHANNEL_ALPHA);
$mask->negateImage(true);
$mask->edgeImage(20);
$mask->opaquePaintImage("white","blue",65000,false);
//// TODO: I don't know how to fill the holes
$mask->transparentPaintImage("black",0.0,0,false);
$image->compositeImage($mask,Imagick::COMPOSITE_DEFAULT,0,0);
I referenced this question:
Outline a transparent image using imagick PHP
This is the image:
This is what I want to achieve:
This is not what I want to achieve:
This is how I would do it in ImageMagick command line.
Make the background under the transparency blue.
Extract the alpha channel.
Dilate the alpha channel.
Use connected components to fill in any "holes" smaller than some threshold in area.
Replace the old alpha channel with the new one
Input: from here
convert cartoon_girl.png -background blue -alpha background \
\( -clone 0 -alpha extract \
-morphology dilate diamond:12 \
-define connected-components:mean-color=true \
-define connected-components:area-threshold=500 \
-connected-components 8 \) \
-alpha off -compose copy_opacity -composite \
result.png
Unfortunately, Imagick does not support connected components as far as I know. So the only other way would be to use flood fill at some point inside each "hole". That means you have to pick x,y coordinate inside each hole to use for doing the flood fill after doing the dilate. See https://www.php.net/manual/en/imagick.floodfillpaintimage.php
convert cartoon_girl.png -background blue -alpha background \
\( -clone 0 -alpha extract \
-morphology dilate diamond:12 \
-fuzz 80% -fill white \
-draw "color 100,310 floodfill" \
-draw "color 200,235 floodfill" -alpha off \) \
-alpha off -compose copy_opacity -composite \
result2.png

IMagick check lightness image

I need to be able to write some text automatically inside an image. According to the image lightness, the script must write in white or black.
So how do I check the lightness/darkness of an image with Imagick?
You could do something like this:
// Load the image
$imagick = new Imagick("image.jpg");
// convert to HSL - Hue, Saturation and LIGHTNESS
$imagick->transformImageColorspace(imagick::COLORSPACE_HSL);
// Get statistics for the LIGHTNESS
$Lchannel = $imagick->getImageChannelMean(imagick::CHANNEL_BLUE);
$meanLightness = $Lchannel['mean']/65535;
printf("Mean lightness: %f",$meanLightness);
If you want to do undercoloured text, per Fred's suggestion, you can do that in PHP with:
$image = new Imagick("image.jpg");
$draw = new ImagickDraw();
$draw->setFillColor('#ffffff');
$draw->setFontSize(24);
$draw->setTextUnderColor('#ff000080');
$image->annotateImage($draw,30,50,0,"Undercoloured Text");
$image->writeImage('result.jpg');
You could also just create a text image on some background color and overlay that on the image. Or use -undercolor with -draw or -annotate. That way, you do not have to worry about the color of the image. Or you could specify the region where you want to write text over, then get the average lightness of that region. Then test if the region is brighter or darker than mid-gray. If brighter, then create a text image of the same size with transparent background and use black text color. Similarly if darker, use white text color. So in ImageMagick command line, these would be:
Input:
Pink Undercolor:
convert logo.png \
\( -size 110x -background pink -font ubuntu-bold -fill $textcolor label:"Testng" \) \
-gravity northwest -geometry +395+400 -compose over -composite result3.png
Testing (dark region) - Unix syntax:
test=`convert logo.png -crop 110x36+395+400 +repage -colorspace gray -format "%[fx:(mean>0.5)?1:0]" info:`
if [ $test -eq 1 ]; then
textcolor="black"
else
textcolor="white"
fi
convert logo.png \
\( -size 110x -background none -font ubuntu-bold -fill $textcolor label:"Testng" \) \
-gravity northwest -geometry +395+400 -compose over -composite result1.png
Testing (bright region):
test=`convert logo.png -crop 110x36+100+400 +repage -colorspace gray -format "%[fx:(mean>0.5)?1:0]" info:`
if [ $test -eq 1 ]; then
textcolor="black"
else
textcolor="white"
fi
convert logo.png \
\( -size 110x -background none -font ubuntu-bold -fill $textcolor label:"Testng" \) \
-gravity northwest -geometry +100+400 -compose over -composite result2.png
Sorry, I do not know Imagick. So someone else may need to help on that.

Extracting certain parts on image with PHP

I would like to be able to extract radar data from gif which occurs every hour.
This is an example of one gif:
Data colors can vary according data legend on the right. I would also like that country borders are not visible, as gif is drown in order: base layer, radar data layer, borders layer - I only need pure radar data.
Any suggestion or solution will be very much appriciated!
All the radar data seems to be highly saturated, so you could extract the saturation onto its own layer and threshold it at, say, 85% and use that as the opacity like this:
convert radar.gif \
\( +clone -colorspace hsl -channel S -separate -threshold 85% \) \
-compose copyopacity -composite result.gif
which gives you this, where all the unsaturated colours are now transparent:
As you can see, it is correctly picking up and retaining all the colours in the "key" on the right, but it also picks up the mauve on the left of the image. Let's make that specific tone transparent:
convert radar.gif \
\( +clone -colorspace hsl -channel S -separate -threshold 85% \) \
-compose copyopacity -composite \
-fuzz 10% -fill none -opaque "rgb(160,153,255)" result.gif
which gives this:
Now, I presume we need to get rid of the sickly yellow too:
convert radar.gif \
\( +clone -colorspace hsl -channel S -separate -threshold 85% \) \
-compose copyopacity -composite \
-fuzz 10% -fill none \
-opaque "rgb(160,153,255)" \
-opaque "rgb(254,251,175)" result.gif
Finally, let's crop to the top left 480x480 px:
convert radar.gif -crop 480x480+0+0 +repage \
\( +clone -colorspace hsl -channel S -separate -threshold 85% \) \
-compose copyopacity -composite \
-fuzz 10% -fill none \
-opaque "rgb(160,153,255)" \
-opaque "rgb(254,251,175)" result.gif
You can use 'imagecreatefromgif' to retrieve the gif and load it as an GD object (requires GD enabled in the php.ini). From there you can use quite a few image manipulation tricks to cut down to what you want from the gif. The PHP.net site has an example on what you can do with it.
First of all, if you are interested just in the information coded by colours, which us present in some specific frame of the gif, read here about how you can access only one frame if that gif:
Accessing gif frames
After that, considering you have a rectangle image, you can scan pixel by pixel, as a matrix, using php function 'imagecolorat'.

JPG -> PNG Release outer background

I do have fowllowing article pics, here as an example a mirror. Of course there can be other geometric forms like bottles, chairs.
The pictures are all in JPEG-format. I want to convert these files to PNG-format. But I want to get rid of the outer white background.
Is there a way to do it by script in php oder ImageMagick?
You can do it like this:
convert frame.jpg -fuzz 10% -fill none -draw 'color 10,10 floodfill' result.png
I have drawn the effect in red here so you can see it.
You can use ImageMagick's -draw to isolate a color, and "floodfill" it to transparency.
convert input.jpg \
-fill transparent \
-fuzz 20% \
-draw 'color 15,15 floodfill' \
out.png
See Color Fill Primitives for other great examples.
For PHP's Imagick library, you would do something like...
$img = new Imagick('input.jpg');
$draw = new ImagickDraw();
$draw->setFillColor('transparent');
$draw->color(15,15, Imagick::PAINT_FLOODFILL);
$img->drawImage($draw);
$img->writeImage('out.png');

Categories