enclose jpg in png 'border'

Questions and postings pertaining to the usage of ImageMagick regardless of the interface. This includes the command-line utilities, as well as the C and C++ APIs. Usage questions are like "How do I use ImageMagick to create drop shadows?".
Post Reply
rnstr

enclose jpg in png 'border'

Post by rnstr »

I searched on the forums but can't find this specific issue:
I built a script that combines a png over a jpg; the border png is like this:
Image
And adding a picture like f.e. http://www.germes-online.com/direct/dbi ... oy_Car.jpg with this command:

Code: Select all

convert img/car.jpg	img/border.png -resize 150x150> \ -resize 100x100! \ -composite -quality 100	img/result.jpg
will create:
Image
But, the problem is, the outside of the border png is white.
So when you put a picture like this on a red background, you'll still get a white rectangle.
How can I, when I'd use a border png that's absolutely transparent like this one:
Image
make sure that only this INSIDE of this transparant border is filled up with the source image?

Thanks in advance!
Last edited by rnstr on 2008-11-14T09:21:00-07:00, edited 2 times in total.
rmagick
Posts: 245
Joined: 2006-03-16T17:30:48-07:00
Location: Durham, NC, USA

Re: enclose jpg in png 'border'

Post by rmagick »

The JPEG format doesn't support transparency. Save the resulting image as a PNG or GIF instead.
rnstr

Re: enclose jpg in png 'border'

Post by rnstr »

Thank you for your answer, but then again, the image underneath it (in this case, the car) would also appear outside the blue 'border'.
el_supremo
Posts: 1015
Joined: 2005-03-21T21:16:57-07:00

Re: enclose jpg in png 'border'

Post by el_supremo »

What you do is extract the alpha channel from border.png, negate it and then use it as a mask over the toy car:

Code: Select all

convert -size 100x100 xc:red \( Toy_Car.jpg -resize 150x150> -resize 100x100! \( img/border.png -channel a -separate -negate -alpha off \) -compose copyopacity -composite \) -compose over -composite toy_out.jpg
I have assumed that you don't need to resize the border image so this only resizes the toy_car image.
You can of course simplify this by preparing the mask beforehand:


Pete
Sorry, my ISP shutdown all personal webspace so my MagickWand Examples in C is offline.
See my message in this topic for a link to a zip of all the files.
el_supremo
Posts: 1015
Joined: 2005-03-21T21:16:57-07:00

Re: enclose jpg in png 'border'

Post by el_supremo »

Fred has pointed out to me a problem with the command I posted. I didn't make it clear which image I was using as the "border" image - it is the skin01.png one, not the completely transparent one.

Pete
Sorry, my ISP shutdown all personal webspace so my MagickWand Examples in C is offline.
See my message in this topic for a link to a zip of all the files.
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: enclose jpg in png 'border'

Post by anthony »

Summery of goal... You have an image that encloses a shape but with transparency both inside and outside. You want to overlay the border on the image but make the parts outside the border transparent RIGHT!

This needs two images... the border (transparent both inside and out) and a mask to cut the unwanted parts! A technique known as DOUBLE masking!

The tricky part is creating that outside cut mask!

WARNING: as you never gave a original transparency image. Next time give the starting ACTUAL image!

The generation of the mask is tricky. because you not only need it to represent all the areas that need to be removed, )or retained. it does not matter which). But you also need it to NOT just stop at the very edge of the border (either the inside edge or outside edge. BOTH are bad.

What you want is for the mask to cover a little way INTO the border and beyond the anti-aliasing edging pixels. Better still the mask should extent to the very middle of the border!

This type of operation is known as morphology, and we apply it using the blur in then next command and Fred Weinhaus has a script for morphology type operations. http://www.fmwconcepts.com/imagemagick/ ... /index.php
Also see Wikipedia
http://en.wikipedia.org/wiki/Mathematical_morphology

This type of operations have NOT been built into IM yet (but it will be added at some point)

This sounds easy but it isn't. What can make it difficult, especially in the example border given is how the line separates into two lines close to each other (on the right). You need to make sure that the space between these two lines remain classed as 'outside'.

In this example we do not have those 'close lines' on the inside of the image so we can generate the mask using the inside edge. So for this case it is easier to find a mask basied on the inside edge of the image.

OKAY steps.

If you had given me the original image I would first convert that to a mask using -alpha extract and then use morphology to convert that down to a just a center line (a morphological skeleton!)

As you have NOT given me the original to work with. so I'll fudge a mask of the inside of the image.

Code: Select all

convert skinexample.png -colorspace gray \
        -fuzz 38% -fill black -floodfill +50+50 white \
        -fill white +opaque black
        skin_mask_inside.png
the -fuzz percentage in the above should be made as large as posible without the inside leaking to the outside.

Now this make need to be morphologically expanded by a couple (2) pixels (morphological 'Dilation'). This uses a trick that was discovered by Fred Weinhaus, that does a square 'averaging' blur.

Code: Select all

convert skin_mask_inside.png -blur 2x65535 \
       -threshold 99% skin_mask_inside_larger.png
Ok we now have out 'cut' mask.

Take the image and use that mask to make the outside parts transparent, and THEN overlay the border.

If you provide me with a copy of the ORIGINAL border image, I'll write all this up in IM Examples with images to follow!

Please contribute it. a more complex border would be better so we can go into more difficult cases, producing a more general method.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: enclose jpg in png 'border'

Post by fmw42 »

rnstr wrote:I searched on the forums but can't find this specific issue:
I built a script that combines a png over a jpg; the border png is like this:
Image
And adding a picture like f.e. http://www.germes-online.com/direct/dbi ... oy_Car.jpg with this command:

Code: Select all

convert img/car.jpg	img/border.png -resize 150x150> \ -resize 100x100! \ -composite -quality 100	img/result.jpg
will create:
Image
But, the problem is, the outside of the border png is white.
So when you put a picture like this on a red background, you'll still get a white rectangle.
How can I, when I'd use a border png that's absolutely transparent like this one:
Image
make sure that only this INSIDE of this transparant border is filled up with the source image?

Thanks in advance!
This is a kind of simplistic approach.

convert \( Toy_Car.jpg -alpha off -resize '150x150>' -resize 100x100! \) \
\( skin01.png -fuzz 30% -fill red -opaque white \) \
-compose over -composite Toy_Car_Red.jpg

The first parenthesis resizes the car image to:
Image

The second parenthesis makes the outside of the blue mask red. So that this:
Image

becomes this:
Image

The command line produces this:
Image

No attempt here at antialiasing the blue ring as Anthony is suggesting could be done.
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: enclose jpg in png 'border'

Post by anthony »

fmw42 wrote:The command line produces this:
Image

No attempt here at antialiasing the blue ring as Anthony is suggesting could be done.
Which is why you see a whitish border between the blue and red background.

IF you are NOT trying to make the outside transparent, and as only a simple gradient of only two colors are involved, you can get a simple anti-aliased solution by doing a linear color modification (ignoring transparency channel)

original color limits....
blue: #0AABFF
white: white.

Now first map that blue to black.

Code: Select all

  convert skin01.png -level-colors '#0AABFF',white  skin_grayscale.png
ERROR: for some reason the whte turns to yellow. I think that is because blue channel is thresholded!

The better alturnative is to extract the most 'different' channel (red) and level that. This should NOT have been needed!

Code: Select all

convert skin01.png -channel RA -separate +channel \
         -negate -compose CopyOpacity -composite -negate \
         skin_grayscale.png 
Image

Now this can be color modified to any color gradient you like!

For example you can make a Red border on a Green background

Code: Select all

convert skin_grayscale.png\
        +level-colors Red,Green   skin_red_on_green.png 
Image
This still retains all the anti-aliasing features of the original, but can be ANY color you like!

ASIDE: This may also let ME recover the original transparency of the outside edge!

It is transparency masking while preserving anti-aliasing that is much harder, but if you do that ONCE, then you can flatten the result to ANY background color or even another image! Much more general.

Again better if the original image could be given so that a proper clipping mask can be generated, to allow for 'double masking'.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
rnstr

Re: enclose jpg in png 'border'

Post by rnstr »

Excuse me for responding so late, I couldn't get to the forums yesterday.
You guys are great, thanks a lot. I don't understand everything that's being elaborated here but I'll try to get it to work.
I'm sorry I didn't include the original transparent image, for that case, to make it clear I used the checkerboarded one :)
But here's the original, I understand that it's a lot 'easier' for the mask to use that one instead of the white-outside one.
Image
I'll go try it all out and let you guys know! Thanks again.

[edit]
As a response to Anthony, I like the double masking idea and for using it in ImageMagick examples.
Here's some more complex border:
Image
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: enclose jpg in png 'border'

Post by anthony »

FYI....

I have added to thumbnails, an outline of the double masking idea, that was later used in the other fancy border examples.

I repeat here that it is very important that the mask edge does not match up to the very edge of the overlay, or you will either get a color blending problem, producing either a color blend or incorrect transparency issue.

I'll see if I can add (in transforms) methods of generating various masks from an example border image such as you have now provided, though I may generate a thicker border fuzzy border with 'holes' that will allow me to illustrate the methods better.

The KEY with all of this is attempting to preserve any and all anti-aliasing properities in the results for the best effect.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
Post Reply