Page 1 of 1
How Do I Do This?
Posted: 2009-05-07T14:07:08-07:00
by jboss2
I have a program that deals with images with transparent backgrounds. I want to chop the transparency off of the bottom of each image up to where a color, any color starts - without affecting anything else with the image. The starting point of the seemingly random color could begin at any point within the image. It is whatever the user uploads.
I have been playing with variants of this command with minimal success:
C:\Program Files\ImageMagick-6.4.1-Q16>convert "C:\Documents and Settings\JBoss2\D
esktop\LogoNone.png" -gravity South -chop 0x1 trim_south.png
I can get it to trim, but it does all sides unless there is a color background present. I just want the south side trimmed. Is this possible? If so how?
Re: How Do I Do This?
Posted: 2009-05-07T15:36:14-07:00
by fmw42
see
http://www.imagemagick.org/Usage/crop/#trim_oneside
or a one-sided variant of my 2-sided trim at
http://www.fmwconcepts.com/imagemagick/ ... rim_2sides
In fact, I am working on a script now to trim any number of sides, but it is not quite finished -- later today or tomorrow, probably.
Re: How Do I Do This?
Posted: 2009-05-07T19:38:15-07:00
by anthony
Fred, your two side trim example is interesting but has the problem of requiring you to know what the border color that is being trimmed is. That may not always be the case, but makes the problem very difficult to solve.
On the other hand, adding a border of a specific color to an image being trimmed is a good way to restrict trim to a specific color (or near a specific color if -fuzz is also used).
Re: How Do I Do This?
Posted: 2009-05-07T20:04:08-07:00
by fmw42
Anthony,
Yes, I see your point. Unfortunately, I am mostly done with the script. I will have to think about whether a complete change is in order. In any event, the advantage of my method is that I can trim any number of sides (1,2,3 or 4) and be specific about which ones.
One way to compromise that I will think about is simply averaging the 4 corner pixels to get the default for the border color. The other issue with my current script development is that it needs a safe color. Is there some quick way to get the complement of some particular color to use that for the safe color other than 255-r,255-g,255-b kind of calculation? All that it needs is to be "more distant" from the background color than needed by -fuzz so as it will be distinguished from the border color.
Note, your method also needs to use some safe color and another color for the two 1-pixel wide borders you add.
It would really be neat if -trim was made to be -gravity sensitive, but I guess to achieve that, one needs to do something similar to either of our methods. I don't see any way around needing a safe color.
Re: How Do I Do This?
Posted: 2009-05-07T21:55:19-07:00
by anthony
fmw42 wrote:In any event, the advantage of my method is that I can trim any number of sides (1,2,3 or 4) and be specific about which ones.
Yes, and something I have wanted to get trim to do for some time. I mean internally it just trims from each side using four loops, it would not take much to add if statements around each loop.
The problem however has been more about the interface while preserving backward compatibility.
Something like
+trim {edge}
One way to compromise that I will think about is simply averaging the 4 corner pixels to get the default for the border color.
that would not work if the image does not have a border on those sides
The other issue with my current script development is that it needs a safe color. Is there some quick way to get the complement of some particular color to use that for the safe color other than 255-r,255-g,255-b kind of calculation? All that it needs is to be "more distant" from the background color than needed by -fuzz so as it will be distinguished from the border color.
That is a negate, and it is never 'most distant' a perfect grey's negate is... a perfect grey! No good.
Also their is nothing to stop fuzz from being larger than 50% in which case a perfect gray is always going to match any 'seed' color that was used!
The way you work however is to add a color to each edge. Well solution read the color for two pixels from each edge (8 colors total but as at least one edge is getting trimmed only 6 colors maximum is needed). then replace those pixels one with black the other white. Hey presto that edge will never trim, unless fuzz is larger than 100% which would mean the whole image is to be trimmed regardless of which edge you start at!
Note, your method also needs to use some safe color and another color for the two 1-pixel wide borders you add.
No it does not. I add those colors, and I add two of them to ensure that only one of those colors will be removed, regardless of what happens. That is I add two pixel strips, trim, then remove one pixel strips.
It would really be neat if -trim was made to be -gravity sensitive, but I guess to achieve that, one needs to do something similar to either of our methods. I don't see any way around needing a safe color.
You don't need a safe color, just two opposite colors (black and white) on an edge to prevent that edge from being trimmed.
Better still It should be easy to FIX IM to allow it to only do one edge! We only need the syntax, and a look at what else should be added while we are at it!
Re: How Do I Do This?
Posted: 2009-05-08T06:23:32-07:00
by jboss2
The link to the article was the one I was working off of.
convert trim_oneside.gif -gravity East -chop 5x0 trim_west.gif
One of the problems I'm having is I haven't seen a clear definition of what the chop arguments are. I'm assuming 5x0 means 5 pixels off of the eastern edge.
In the example, the border is added and then lopped off. Now adding a 5 pixel border and lopping it off is all well and good. Having added it, I would know how big it is. I have borderless images. The side I want to take off could be 1 pixel wide, 5 pixels wide or 250 pixels wide. It's different every time. What I do know is when I hit the color red, black, white, green or whatever the user picked for the font color of the image (image is user typing captured in a snapshot in Flash) that I want to remove all transparency up to that color, but only on the south side. If I remove any the transparency on the north and west sides, it messes up the x and y values of where the modified image needs to be replaced.
This is a pretty complex program I'm working with. I'm just simplifying for the example.
Re: How Do I Do This?
Posted: 2009-05-08T10:17:23-07:00
by fmw42
Anthony wrote:Yes, and something I have wanted to get trim to do for some time. I mean internally it just trims from each side using four loops, it would not take much to add if statements around each loop.
The problem however has been more about the interface while preserving backward compatibility.
Something like +trim {edge}
Why not simply -gravity ... -trim? Unless you want to allow more than one edge to be trimmed and then you need something like:
+trim {edge list}
Obviously fixing IM would be the best solution.
Anthony wrote:that would not work if the image does not have a border on those sides
The whole point of my current script assumes that there is a border on all sides and one wants to trim one or more sides (although it allows all four sides to be trimmed). It may not be optimal, but seems to work.
The way you work however is to add a color to each edge. Well solution read the color for two pixels from each edge (8 colors total but as at least one edge is getting trimmed only 6 colors maximum is needed). then replace those pixels one with black the other white. Hey presto that edge will never trim, unless fuzz is larger than 100% which would mean the whole image is to be trimmed regardless of which edge you start at!
I will have to think about this. Which two pixels on each edge? What if they are the corners? I presume the best solution is two pixels as close to the middle of the edge. Then after trimming, you replace those pixels. Is that the idea? What if the border is either white or black? Then you have to find other colors besides white or black!!! So seems like you still need to know some safe color
But I probably will finish the script as is. Then perhaps later come back to it with this potentially better solution.
Anthony wrote:No it does not. I add those colors, and I add two of them to ensure that only one of those colors will be removed, regardless of what happens. That is I add two pixel strips, trim, then remove one pixel strips.
What if one or the other color is the same as the background?
Re: How Do I Do This?
Posted: 2009-05-08T12:35:20-07:00
by jboss2
I think this discussion is great...but the short answer is I can't do what I want, right?
Re: How Do I Do This?
Posted: 2009-05-08T14:48:03-07:00
by fmw42
If you know exactly how many rows you want to remove from the south or bottom of the image, the all you need do is
convert image.png -gravity south -chop 0xN image_south_chopped.png
This command works perfectly fine for me for an image that has a transparent border around it and I can remove any number of rows on the bottom side only. IM 6.5.2-3 Q16 Mac OSX Tiger
where N is the number of rows to remove from the south side. Note you must be using gif or png format if you have an image with transparency. If you remove all transparency, then your output can be jpg or any other. But if you still have sides with transparency, then you must use png or gif for the output.
If you don't know the number of rows you need to remove, then you need to use -trim as per Anthony's example or mine suggested above in my earlier post in order to modify -trim to remove on only one side.
If you don't follow this, then provide an example image and we will show you how to process it, if possible.
Re: How Do I Do This?
Posted: 2009-05-08T20:15:07-07:00
by anthony
jboss2 wrote:One of the problems I'm having is I haven't seen a clear definition of what the chop arguments are. I'm assuming 5x0 means 5 pixels off of the eastern edge.
Yeap BUT you should probably give a +0+0 as well just to be safe.
All the chop methods and options are given in IM Examples, Cutting and Bordering.
http://www.imagemagick.org/Usage/crop/#chop
Re: How Do I Do This?
Posted: 2009-05-13T07:16:11-07:00
by jboss2
C:\Program Files\ImageMagick-6.4.1-Q16>convert "C:\Documents and Settings\Josh\D
esktop\LogoNone.png" -background none -trim{South} trim_south.png
This does nothing to the image. I still have a large blank space on the bottom.
C:\Program Files\ImageMagick-6.4.1-Q16>convert "C:\Documents and Settings\Josh\D
esktop\LogoNone.png" -trim{South} -background none trim_south.png
Reversing this also does nothing to the image.
Original:
After running both commands:
Re: How Do I Do This?
Posted: 2009-05-13T10:57:53-07:00
by fmw42
C:\Program Files\ImageMagick-6.4.1-Q16>convert "C:\Documents and Settings\Josh\D
esktop\LogoNone.png" -background none -trim{South} trim_south.png
There is no such thing as -trim{South}, it is only -trim. Trim has no arguments and even if it did it would not be using the {...} syntax you are trying. Trim by itself blindly tries to trim all around, if it can. The only way to avoid that is to use either Anthony's method or mine. I will try to make an example for you. But see below.
You actually have a very strange image. The image is totally black and the text is written in the alpha channel. This is not really a good way and may be causing problems with trim.
Also I seem to be having trouble making a better image with proper transparency and the text in the image. I am reporting this issue to see if it is a bug or my problem and will get back on this to you.
viewtopic.php?f=3&t=13770
Re: How Do I Do This?
Posted: 2009-05-13T12:13:30-07:00
by fmw42
My IM 6.5.2-4 is having trouble saving transparency to png. So this should work, but I had to save as gif, which, because your text is not totally black and white and put into the alpha channel rather than the image, it loses the underline and loses the antialiasing with gif as I had to make the alpha channel binary. Note my images are gifs, but with some other version of IM, the png should work and leave the underline and antialiasing.
This will trim all around:
convert LogoNone.png -trim +repage LogoNone_trim.png
This will trim only on the south side, but is more complex than Anthony's method for just one side:
convert LogoNone.png \
-background none -gravity north -splice 0x1+0+0 \
-background none -gravity east -splice 1x0+0+0 \
-background none -gravity west -splice 1x0+0+0 \
-size 1x1 xc:white -gravity north -compose over -composite \
-size 1x1 xc:white -gravity east -compose over -composite \
-size 1x1 xc:white -gravity west -compose over -composite \
-trim +repage \
-gravity north -chop 0x1+0+0 \
-gravity east -chop 1x0+0+0 \
-gravity west -chop 1x0+0+0 \
logoNone_trim_south.png
or Anthony's method (which is shorter for one side):
convert LogoNone.png \
-background white -gravity north -splice 0x1+0+0 \
-background black -gravity north -splice 0x1+0+0 \
-trim +repage \
-gravity north -chop 0x1+0+0 \
LogoNone_trim_south2.png
Re: How Do I Do This?
Posted: 2009-05-13T18:10:55-07:00
by anthony
jboss2 wrote:I think this discussion is great...but the short answer is I can't do what I want, right?
Going back your your original problem.
Use the first link that was given. Add the two extra color rows to the top of the image, trim, then remove the one extra color row that is left. The result is that only the bottom will be trimmed according to what ever 'fuzz' factor you use.
If transparency is giving problems (which I noted you reported in the bugs forum, and cause by changed to PNG in the very latest release), and all the colors are black. (Which is actually quite a common image!) then a simple solution is to just extract the alpha channel and deal with it as a greyscale image! EG use
-alpha extract
When you are finished you can restore the transparency by using
-background black -alpha shape
Re: How Do I Do This?
Posted: 2009-05-14T16:41:29-07:00
by fmw42
I finally finished my script to trim on any number of sides. See trimmer at
http://www.fmwconcepts.com/imagemagick/index.html