[SOLVED] Better way to produce this png ?

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?".
Totor
Posts: 10
Joined: 2010-11-26T13:04:13-07:00
Authentication code: 8675308

[SOLVED] Better way to produce this png ?

Post by Totor »

Hi,

I guess to be in the good place.

I've a question : is there a better way to produce this image :
Image

my way (under linux) :

Code: Select all

$convert --version
Version: ImageMagick 6.5.7-8 2009-11-26 Q16 http://www.imagemagick.org
Copyright: Copyright (C) 1999-2009 ImageMagick Studio LLC
Features: OpenMP 

$convert -size 320x200 xc:none -stroke snow4 -fill snow2 -draw 'roundrectangle 16,110,304,190 20,40' -fill snow -draw 'roundrectangle 264,110,304,190 20,40' -fill chartreuse3 -draw 'roundrectangle 16,110,289,190 20,40' -fill chartreuse2 -draw 'roundrectangle 249,110,289,190 20,40' -fill none -draw 'roundrectangle 264,110,304,190 20,40' -strokewidth 2 -draw 'roundrectangle 16,110,304,190 20,40' '(' +clone -background snow4 -shadow 80x3+3+3 ')' +swap -background none -layers merge -size 320x100 xc:none -strokewidth 0 -gravity center -font ./Garfield.ttf -pointsize 80 -fill red 'label:95 %' '(' +clone -background firebrick3 -shadow 80x3+3+3 ')' +swap -background none -layers merge image.png
Thank's !

NB : Sorry my English is pretty poor (I'm French)
Last edited by Totor on 2010-11-28T14:29:37-07:00, edited 2 times in total.
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: Better way to produce this png ?

Post by anthony »

You seemed to have done well.
Though I would have broken up the lone LONG line into a multi-line statement so as to make it easier to read and figure out what is going on. I have broken it up for UNIX/Linux. but you can also do this (differentally) for DOS scripts

Interesting use of round rectangle to make long cylinders and matching ellipses
I would never have thought of it! Very well done. This example could be a good IM demo!

Also your generation of a second image -size 320x100 xc:none seems to be useless! I also would not recommend the use of strokewidth 0 See Draw, Stroke and Strokewidth Better to create a larger font and shrink if you only want a 'thin' border. Stroke widths smaller than 1 has always been a little awkward in IM draw.
Question where did you get Garfield font from?

Code: Select all

  convert -size 320x200 xc:none \
         -stroke snow4 -fill snow2 -draw 'roundrectangle 16,110,304,190 20,40' \
         -fill snow -draw 'roundrectangle 264,110,304,190 20,40' \
         -fill chartreuse3 -draw 'roundrectangle 16,110,289,190 20,40' \
         -fill chartreuse2 -draw 'roundrectangle 249,110,289,190 20,40' \
         -fill none -draw 'roundrectangle 264,110,304,190 20,40' \
         -strokewidth 2 -draw 'roundrectangle 16,110,304,190 20,40' \
         '(' +clone -background snow4 -shadow 80x3+3+3 ')' +swap \
         -background none -layers merge \
         '(' -strokewidth 0 -font ./Garfield.ttf -pointsize 80 -fill red \
                -size 320x100 -gravity center label:'95 %'  \
             '(' +clone -background firebrick3 -shadow 80x3+3+3 ')' +swap ')' \
          -background none -layers merge \
          image.png
That can be put in a script and you can now easilly insert bug lines like -write x:
that will display and wait between the various statements. Makes debugging and figuring out the command a LOT easier. See Basics, Complex Image Processing and Debugging

All that is needed is needed is to do some pixel math to draw the cylinder at different percentages :-)

In such as script I would create two completely separate images, one to draw the cylinder and another to draw the label according to 'user arguments'. Then just append the images rather than overlay as you get more freedom to modify positions or adjust things, for new situations and needs.

I created such a script, then modified it to generate an animation of each of the drawing steps for just the cylinder (not the shadowing or label...
Image

Of course gif does not handle transparency very well so the edge is very aliased ('staircased')
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: Better way to produce this png ?

Post by anthony »

PS: it is posible to have a script generate MVG drawing commands and feed that directly into convert to draw the cylinder. Though you can not do the shadowing steps in that mode.

See...Reading MVG Files
http://www.imagemagick.org/Usage/draw/#reading

But if you do it this way the MVG commands are then easily generated by the script along with all the calculations and adjustments needed for doing... percentages... or even cylinders of different thickness and lengths. It would make the whole thing more controllable.

If you do this, please let us know!
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
Totor
Posts: 10
Joined: 2010-11-26T13:04:13-07:00
Authentication code: 8675308

Re: Better way to produce this png ?

Post by Totor »

hi,
anthony wrote:You seemed to have done well.
Though I would have broken up the lone LONG line into a multi-line statement so as to make it easier to read and figure out what is going on. I have broken it up for UNIX/Linux. but you can also do this (differentally) for DOS scripts
I've try but i got an error and because it was not my priority, i fell tried.
anthony wrote: Interesting use of round rectangle to make long cylinders and matching ellipses
I would never have thought of it!
At the begenning i've used circle but i've found it much more difficult and less accurate.
anthony wrote: Very well done. This example could be a good IM demo!
I'm so surprised because it's my first drawing and i spent considerable time !
thank you very much, it's an honor
anthony wrote:Also your generation of a second image -size 320x100 xc:none seems to be useless!
i've tried with only one but i had difficulties to put the text at the good location :?
anthony wrote: I also would not recommend the use of strokewidth 0 See Draw, Stroke and Strokewidth Better to create a larger font and shrink if you only want a 'thin' border. Stroke widths smaller than 1 has always been a little awkward in IM draw.
well I replaced it by a stroke of "1" and with the shadow color.
it makes much better !
anthony wrote: Question where did you get Garfield font from?
there
anthony wrote:That can be put in a script and you can now easilly insert bug lines like -write x:
that will display and wait between the various statements. Makes debugging and figuring out the command a LOT easier. See Basics, Complex Image Processing and Debugging
Very interesting, if I knew I had much less difficulty because I do not know the first thing in computer graphics!
anthony wrote: All that is needed is needed is to do some pixel math to draw the cylinder at different percentages :-)
In fact, the script is already done and everything is calculated and proportional.
My goal was to create a dynamic icon for "zenity". Here's the script:

Code: Select all

#!/bin/bash

trap 'end 1' SIGINT SIGKILL

font="${1:-./Garfield.ttf}"
imgXSize="${2:-320}"
imgYSize="${3:-200}"

resultat=.$$_resultat.png

borderColor=snow4
cylindreOutColor=snow2
cylindreInColor=snow
progressOutColor=chartreuse3
progressInColor=chartreuse2
texteColor=red
progressYmax=$(((imgYSize*95)/100)) 
progressYmin=$(((imgYSize*55)/100))
progressXmin=$(((imgXSize*5)/100))
progressXmax=$((imgXSize-progressXmin))
wc=$(((progressYmax-progressYmin)/4))
hc=$(((progressYmax-progressYmin)/2))
fontSize=$(((imgYSize*2)/5)) # 40%
fontShadow=firebrick3

end()
{
#	[ -f "${resultat}" ] && rm "${resultat}"
	exit $1
}

makeIcon()
{ 
	texte="$1"
	pct=$2

	max=$((progressXmin+pct*(progressXmax-progressXmin)/100)); 
	((max<progressXmin+2*wc)) && max=$((progressXmin+2*wc))
	
	resultat=image.png
	convert -size ${imgXSize}x${imgYSize} xc:none -stroke ${borderColor} -fill ${cylindreOutColor} -draw "roundrectangle ${progressXmin},${progressYmin},${progressXmax},${progressYmax} ${wc},${hc}" \
	-fill ${cylindreInColor} -draw "roundrectangle $((progressXmax-2*wc)),${progressYmin},${progressXmax},${progressYmax} ${wc},${hc}"  \
	-fill ${progressOutColor} -draw "roundrectangle ${progressXmin},${progressYmin},${max},${progressYmax} ${wc},${hc}" \
	-fill ${progressInColor} -draw "roundrectangle $((max-2*wc)),${progressYmin},${max},${progressYmax} ${wc},${hc}" \
	-fill none -draw "roundrectangle $((progressXmax-2*wc)),${progressYmin},${progressXmax},${progressYmax} ${wc},${hc}" \
	-strokewidth 2 -draw "roundrectangle ${progressXmin},${progressYmin},${progressXmax},${progressYmax} ${wc},${hc}" \
	 \( +clone -background ${borderColor} -shadow 80x3+5+5 \) +swap  -background none -layers merge \
	 -size ${imgXSize}x$((imgYSize/2)) xc:none -strokewidth 1 -stroke ${fontShadow} -gravity center -font ${font} \
	 -pointsize ${fontSize} -fill ${texteColor} label:"${texte}"  \( +clone -background ${fontShadow} \
	 -shadow 80x3+5+5 \) +swap -background none -layers merge "${resultat}"

	echo "icon:${resultat}"
	echo "tooltip:${texte}"
}

{
for ((x=0;x<=100;x++))
do
	makeIcon "${x} %" ${x}
done 
#makeIcon "OK !" 100
read -s -n1
} | zenity --listen --notification --window-icon=info --text "0 %"


end 0
anthony wrote: In such as script I would create two completely separate images, one to draw the cylinder and another to draw the label according to 'user arguments'. Then just append the images rather than overlay as you get more freedom to modify positions or adjust things, for new situations and needs.

I created such a script, then modified it to generate an animation of each of the drawing steps for just the cylinder (not the shadowing or label...
I would be interested in such a script, could you post it?

I do not know the MVG script but I do not think this is a good solution because the icon must be processed as quickly as possible and this makes an additional share. That is why I asked if there was a better approach than mine. Namely, is it possible to reduce the time of creating the icon?
I keep this method still below the elbow!

Thank's a lot for evry things ;)
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: Better way to produce this png ?

Post by anthony »

I Already deleted it...

Basically I added a -write miff:-
after each line (step) (skipping the last bit... and then piped the output into

Code: Select all

   | convert - -set delay 200 \
             \( +clone -set delay 500 \) +swap +delete \
             cylinder_const.gif
I used miff as writing it repeatally is equivelent to a multi-image sequence.
The final convert just collects all the images, and sets the appropriate delays 2 second each except the final frame which is 5 seconds.

Hmmm.. here is the fill script, I Just recreated it again..

Code: Select all

#!/bin/sh
convert \
  -size 320x100 xc:none -stroke snow4 \
  -write miff:- \
  -fill snow2        -draw 'roundrectangle 16,  10, 304, 90  20,40' \
  -write miff:- \
  -fill snow         -draw 'roundrectangle 264, 10, 304, 90  20,40' \
  -write miff:- \
  -fill chartreuse3  -draw 'roundrectangle 16,  10, 289, 90  20,40' \
  -write miff:- \
  -fill chartreuse2  -draw 'roundrectangle 249, 10, 289, 90  20,40' \
  -write miff:- \
  -fill none         -draw 'roundrectangle 264, 10, 304, 90  20,40' \
  -write miff:- \
  -strokewidth 2     -draw 'roundrectangle 16,  10, 304, 90  20,40' \
  miff:- |
convert - -set delay 200 \
        \( +clone -set delay 500 \) +swap +delete \
        cylinder_const.gif
I have not gone though your own 'zenity' script. I use zenity a fair bit for various scripts to interface with X windows, but for some things I find zenity a little limited. As such I also use things like
  • "xmessage" which is good for file output and multiple button inputs,
  • "notifier" as a graphical 'tail' type log outputs
  • "Xdialog" as a zenity alternative (with modes for going back or forward, as well as multiple string inputs)
  • as well as xwindow modifiers such as "xwit", "xte" "xdotool". For examle I have a script using xwit that will find a 'zenity' popup, give it focus, and make it 'bounce' to attract the users attention.
My big problem with your script is it uses zenity notifier. This gets resized to fit into the notification area of Gnome panels, so becomes rather tiny on my setup, Still I'll have to look closer at it for the math

Interesting usage of zenity!!! Here was a quick test I did of the method.

Code: Select all

( echo icon:im/images/hand_point.gif; sleep 5; ) | zenity --notification --listen


The use of MVG will probably still result simpler command. But I'll do that later.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
Totor
Posts: 10
Joined: 2010-11-26T13:04:13-07:00
Authentication code: 8675308

Re: Better way to produce this png ?

Post by Totor »

Re,

I've tried to make un 3D effect like your's but i find it too slow :( :

Code: Select all

#!/bin/bash

trap 'end 1' SIGINT SIGKILL

font="${1:-./Garfield.ttf}"
imgXSize="${2:-320}"
imgYSize="${3:-200}"

resultat=.$$_resultat.png

borderColor=snow4
cylindreOutColor=snow2
cylindreInColor=snow
progressOutColor=chartreuse3
progressInColor=chartreuse2
texteColor=red
progressYmax=$(((imgYSize*95)/100)) 
progressYmin=$(((imgYSize*55)/100))
progressXmin=$(((imgXSize*5)/100))
progressXmax=$((imgXSize-progressXmin))
wc=$(((progressYmax-progressYmin)/4))
hc=$(((progressYmax-progressYmin)/2))
fontSize=$(((imgYSize*2)/5)) # 40%
fontShadow=firebrick3

end()
{
#	[ -f "${resultat}" ] && rm "${resultat}"
	exit $1
}

makeIcon()
{ 
	texte="$1"
	pct=$2

	max=$((progressXmin+pct*(progressXmax-progressXmin)/100)); 
	((max<progressXmin+2*wc)) && max=$((progressXmin+2*wc))
	
	resultat=image.png
	convert -size ${imgXSize}x${imgYSize} xc:none -stroke ${borderColor} -fill ${cylindreOutColor} -draw "roundrectangle ${progressXmin},${progressYmin},${progressXmax},${progressYmax} ${wc},${hc}" \
	-fill ${cylindreInColor} -draw "roundrectangle $((progressXmax-2*wc)),${progressYmin},${progressXmax},${progressYmax} ${wc},${hc}"  \
	-fill ${progressOutColor} -draw "roundrectangle ${progressXmin},${progressYmin},${max},${progressYmax} ${wc},${hc}" \
	-fill ${progressInColor} -draw "roundrectangle $((max-2*wc)),${progressYmin},${max},${progressYmax} ${wc},${hc}" \
	-fill none -draw "roundrectangle $((progressXmax-2*wc)),${progressYmin},${progressXmax},${progressYmax} ${wc},${hc}" \
	-strokewidth 2 -draw "roundrectangle ${progressXmin},${progressYmin},${progressXmax},${progressYmax} ${wc},${hc}" \
	 \( +clone -background ${borderColor} -shadow 80x3+5+5 \) +swap  -background none -layers merge \
	 -size ${imgXSize}x$((imgYSize/2)) xc:none -strokewidth 1 -stroke ${fontShadow} -gravity center -font ${font} \
	 -pointsize ${fontSize} -fill ${texteColor} label:"${texte}"  \( +clone -background ${fontShadow} \
	 -shadow 80x3+5+5 \) +swap -background none -layers merge "${resultat}"



	 convert "${resultat}"  -fx A  +matte -blur 0x3  -shade 110x30  -normalize \
          "${resultat}"  -compose Overlay -composite \
          "${resultat}"  -matte  -compose Dst_In  -composite \
          ant_3D.png

#	echo "icon:${resultat}"
	echo "icon:ant_3D.png"
	echo "tooltip:${texte}"
}

{
for ((x=0;x<=100;x++))
do
	makeIcon "${x} %" ${x}
done 
#makeIcon "OK !" 100
#read -s -n1
} | zenity --listen --notification --window-icon=info --text "0 %"
end 0
times wrote:$time progression_3D.sh
real 0m19.621s
user 1m7.410s
sys 0m3.000s


$time progression.sh
real 0m8.133s
user 0m28.690s
sys 0m1.180s
:shock:

thank's for your "fill script", i'll take a look !

- if found notifier (notify-send ?) less flexible
- zenity is based on xdialog.
anthony wrote: Interesting usage of zenity!!! Here was a quick test I did of the method.

Code: Select all

( echo icon:im/images/hand_point.gif; sleep 5; ) | zenity --notification --listen
the options ("icon:", "tooltip:", "visible:" and "message:") are not documented: I had looked into the source code to realize that zenity could have dynamic icons;)
I hope it will serve you!
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: Better way to produce this png ?

Post by anthony »

Yes that is VERY slow. Because of the VERY large blurs involved.

However you could probably shade the first 'curved' part of cylinders using a gradient...

NOTE you do NOT have to worry about the border or stroke for this as you will be re doing that border
in the later parts.

Also I found the Garfield font likes to leave a LARGE space under the font base line. Trimming the label
would help with that.

Hmmm...

Code: Select all

convert -size 320x90 -stroke snow4 \
  \( xc:none \
     -fill snow2 -draw 'roundrectangle 16,  5, 304, 85  20,40' \
     -fill snow  -draw 'roundrectangle 264, 5, 304, 85  20,40' \
  \) \
  \( xc:none \
     -fill chartreuse3 -draw 'roundrectangle 16,  5, 180, 85  20,40' \
     gradient:chartreuse-green -compose ATop -composite -compose Over \
     -fill chartreuse2 -draw 'roundrectangle 140, 5, 180, 85  20,40' \
  \) \
  -compose Over -composite \
  -fill none      -draw 'roundrectangle 264, 5, 304, 85  20,40' \
  -strokewidth 2  -draw 'roundrectangle 16,  5, 304, 85  20,40' \
  \( +clone -background snow4 -shadow 80x3+3+3 \) \
     +swap -background none -layers merge \
  \
  \( -font Garfield -pointsize 80 \
     -strokewidth 1 -fill red label:'50 %' -trim +repage  \
     \( +clone -background firebrick3 -shadow 80x3+3+3 \) \
       +swap -background none -layers merge \) \
  -insert 0 -gravity center -append \
  -background white -gravity center -extent 320x200 \
  cylinder_shaded.png
Image
Here I only shaded the green cylinder as when I shaded the first cylinder (snow1-snow4) the result looked silly. Almost like a separate cylinder was coming from behind the first. What really needs to happen is that the 'snow' cylinder needs to be shaded with a almost completely transparent gradient, so it looks like you are looking though a glass walled tube. This tube can also had all the otehr outlines added too, before being overlaid on the green cylinder. Tthe flat top of the green cylinder also gets a little shading, but that should be 'realistic'.

Also I centered appended the two images, trimmed the 'label' image before creating the shadow to try and get it 'closer' to the cylinder. Then I using -extend to set the final image size (vertically) and underlay a white background. I could probably do the same trimming to cylinders too.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: Better way to produce this png ?

Post by anthony »

After some effort ( and a lot of trail and error as shadows became very difficult) here is my fully shaded version.

Code: Select all

convert -size 320x90 -stroke snow4 \
  \( xc:none \
     -fill chartreuse3 -draw 'roundrectangle 16,  5, 180, 85  20,40' \
     gradient:chartreuse-chartreuse4 -compose ATop -composite -compose Over \
     -fill chartreuse2 -draw 'roundrectangle 140, 5, 180, 85  20,40' \
  \) \
  \( xc:none    -draw 'roundrectangle 16,  5, 304, 85  20,40' \
     gradient:'none-graya(0,.4)' -compose In -composite -compose Over \
     \( xc:none -draw 'roundrectangle 264, 5, 304, 85  20,40' \) \
     -compose DstOut -composite -compose Over \
     -fill 'graya(0,.07)' -draw 'roundrectangle 264, 5, 304, 85  20,40' \
     -strokewidth 2  -draw 'roundrectangle 16,  5, 304, 85  20,40' \
  \) \
  \( xc:none -fill white -draw 'roundrectangle 16,  5, 304, 85  20,40' \
     \( +clone -background snow4 -shadow 80x3+3+3 \) \
  \) \
  -insert 0 -insert 1 -background none -layers merge \
  \
  \( -font Garfield -pointsize 80 \
     -strokewidth 1 -fill red label:'50 %' -trim +repage  \
     \( +clone -background firebrick3 -shadow 80x3+3+3 \
     \) +swap -background none -layers merge \) \
  -insert 0 -gravity center -append \
  -background white -gravity center -extent 320x200 \
  cylinder_shaded_2.png
Image
NOTE shadowing is tricky when the object is semi-transparent already. It just 'goes wrong'. As such for the cylinder shadow, I needed to generate a fully-opaque (white) outline to shadow, and then use it as a background for the other cylinders.

So the final cylinder layers are -- shadow, shaped white backdrop, green cylinder, semi-transparent 'glass' cylinder. 4 images!!!

In summery - I do not think it was worth the effort. Just green cylinder shading should be enough.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
Totor
Posts: 10
Joined: 2010-11-26T13:04:13-07:00
Authentication code: 8675308

Re: Better way to produce this png ?

Post by Totor »

wahouuu, something that is almost what I wanted to get;)

it will take me some time to digest this: I do not quite understand because I do not know the use and manipulation of colors / images

I've put this in my script and I get something very powerful with the "full shadow" version.

i'll try to work on it to finalize one thing
if i have a problem i'll told you ...

thank you very much
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: Better way to produce this png ?

Post by anthony »

I just realised that you do NOT need to compose a gradient Into a shape to color it.
Instead of using a -fill your can set a -tile image (-tile overrides -fill in -draw).

This simplifes the 3D shaded cylinder drawing back to looking like the original simply -draw rounded rectangles! Though using -tiled gradients rather than solid fill colors. And as only opaque colors are used on the transparent background you again do not have 'shadow' generation problems.

Code: Select all

convert -size 320x90 xc:none -stroke snow4 \
  -size 1x90 -tile gradient:white-snow4 \
                   -draw 'roundrectangle 16,  5, 304, 85  20,40' \
  +tile -fill snow -draw 'roundrectangle 264, 5, 304, 85  20,40' \
  -tile gradient:chartreuse-green \
                   -draw 'roundrectangle 16,  5, 180, 85  20,40' \
  -tile gradient:chartreuse1-chartreuse3 \
                   -draw 'roundrectangle 140, 5, 180, 85  20,40' \
  +tile -fill none -draw 'roundrectangle 264, 5, 304, 85  20,40' \
  -strokewidth 2   -draw 'roundrectangle 16,  5, 304, 85  20,40' \
  \( +clone -background snow4 -shadow 80x3+3+3 \) \
     +swap -background none -layers merge \
  \
  \( +size -font Garfield -pointsize 90 \
     -strokewidth 1 -fill red label:'50 %' -trim +repage  \
     \( +clone -background firebrick3 -shadow 80x3+3+3 \) \
       +swap -background none -layers merge \) \
  -insert 0 -gravity center -append \
  -background white -gravity center -extent 320x200 \
  cylinder_shaded_5.png
Image
It probably still needs some more work in color selection, especially the colors used for the end of the green cylinder, as I can't seem to get a gradient that looks like you are viewing it though a glass cylinder.

Maybe making the green cylinder smaller would help to give the glass a little thickness?
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
Totor
Posts: 10
Joined: 2010-11-26T13:04:13-07:00
Authentication code: 8675308

Re: Better way to produce this png ?

Post by Totor »

Well,

I think i've reached my goal !!!

I've work on your last script and had a headache with compositing but finally, i'm happy with the result :

50% :
Image

95%
Image

97%
Image

Note: there is a transition of the color "green" when it reaches the right end of the cylinder.

The script :

Code: Select all

#!/bin/bash

trap 'end 1' SIGINT SIGKILL

font="${1:-./Garfield.ttf}"
imgXSize="${2:-320}"
imgYSize="${3:-200}"

resultat=.$$_resultat.png

borderColor=snow4
cylindreEmptyColor=white-gray
cylindreInsideColor=white-darkgray
cylindreFullColor=green3-DarkGreen
cylindreFullColor2=green2-DarkGreen
cylindreOutColor=lime-Green4
texteColor=red


progressYmax=$(((imgYSize*95)/100)) 
progressYmin=$(((imgYSize*55)/100))
progressXmin=$(((imgXSize*5)/100))
progressXmax=$((imgXSize-progressXmin))
wc=$(((progressYmax-progressYmin)/4))
hc=$(((progressYmax-progressYmin)/2))
fontSize=$(((imgYSize*2)/5)) # 40%
fontShadow=firebrick3

imgYSizeOrigin=${imgYSize}
pct5=$(((imgYSize*5)/100))
((progressYmin=pct5/2))
imgYSize=$((imgYSize*45/100))
((progressYmax=imgYSize-progressYmin))

end()
{
#	[ -f "${resultat}" ] && rm "${resultat}"
	exit $1
}

makeIcon()
{ 
	texte="$1"
	pct=$2

	max=$((progressXmin+pct*(progressXmax-progressXmin)/100)); 
	((max<progressXmin+2*wc)) && max=$((progressXmin+2*wc))
	
	resultat=image.png
	
convert -size ${imgXSize}x${imgYSize} \( xc:none -stroke ${borderColor} \
   -tile gradient:${cylindreEmptyColor} \
                   -draw "roundrectangle ${progressXmin},${progressYmin},${progressXmax},${progressYmax} ${wc},${hc}" \
  -tile gradient:${cylindreFullColor} \
                   -draw "roundrectangle ${progressXmin},${progressYmin},${max},${progressYmax} ${wc},${hc}" \
  -tile gradient:${cylindreFullColor2} \
                   -draw "roundrectangle $((max-2*wc)),${progressYmin},${max},${progressYmax} ${wc},${hc}" \
    \) \
	\( xc:none -stroke ${borderColor} \
			-tile gradient:${cylindreOutColor} \
                   -draw "roundrectangle $((max-2*wc)),${progressYmin},${max},${progressYmax} ${wc},${hc}" \
		\( xc:none -tile gradient:${cylindreInsideColor} \
				-draw "roundrectangle $((progressXmax-2*wc)),${progressYmin},${progressXmax},${progressYmax} ${wc},${hc}"  \) \
				-compose DstAtop -composite \) \
	-compose over -composite \
		-fill none -strokewidth 2 -stroke ${borderColor} -draw "roundrectangle ${progressXmin},${progressYmin},${progressXmax},${progressYmax} ${wc},${hc}" \
		\( +clone -background ${borderColor} -shadow 80x3+3+3 \) \
		+swap -background none -layers merge \
		\( xc:none -fill none -strokewidth 2 -draw "roundrectangle $((progressXmax-2*wc)),${progressYmin},${progressXmax},${progressYmax} ${wc},${hc}" \
			\( +clone -background ${borderColor} -shadow  80x3+3+3 \) \
			+swap -background none -layers merge \
		\) \
		-background none -layers merge \
	\( -font "${font}" -pointsize ${fontSize} \
		-strokewidth 1 -stroke ${fontShadow} -fill red label:"${texte}" -trim +repage  \
		\( +clone -background ${fontShadow} -shadow 80x3+3+3 \
		\) +swap -background none -layers merge \) \
	-insert 0 -gravity center -append \
	-background none -gravity center -extent ${imgXSize}x${imgYSizeOrigin} \
   "${resultat}"
	
	echo "icon:${resultat}"
	echo "tooltip:${texte}"
}

{
for ((x=95;x<=95;x++))
do
	makeIcon "${x} %" ${x}
done 
#makeIcon "OK !" 100
read -s -n1
} | zenity --listen --notification --window-icon=info --text "0 %"

end 0
I wanted to thank you for all your work and all that you have made me discover !
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: [SOLVED] Better way to produce this png ?

Post by anthony »

Something is not quite right with the math!

The 50% output does not look like 50% more like 40%

The transition looks good. Didn't think of that!
Though when looking through the flat end the color should be a solid color.

Hmmm I think making the green cylinder slightly smaller than the outside glass cylinder would also make it look better.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
Totor
Posts: 10
Joined: 2010-11-26T13:04:13-07:00
Authentication code: 8675308

Re: [SOLVED] Better way to produce this png ?

Post by Totor »

anthony wrote:Something is not quite right with the math!

The 50% output does not look like 50% more like 40%
Yes, I realized after posting my reply but I had paperwork to prepare and I went to bed!
I've found the error :
max=$((progressXmin+pct*(progressXmax-progressXmin)/100)); is to be replaced with max=$((progressXmin+2*wc+pct*(progressXmax-2*wc-progressXmin)/100));
But a can't test for now !
anthony wrote: Hmmm I think making the green cylinder slightly smaller than the outside glass cylinder would also make it look better.
probably but this requires additional calculations to keep the proportions!
Totor
Posts: 10
Joined: 2010-11-26T13:04:13-07:00
Authentication code: 8675308

Re: [SOLVED] Better way to produce this png ?

Post by Totor »

well, i've try to have the green cylinder smaller but there is a lack of perspective at the right end :?
Image
Image
Image

i must think about it !

Code: Select all

#!/bin/bash

trap 'end 1' SIGINT SIGKILL

font="${1:-./Garfield.ttf}"
imgXSize="${2:-320}"
imgYSize="${3:-200}"

resultat=.$$_resultat.png

borderColor=snow4
cylindreEmptyColor=white-gray
cylindreInsideColor=white-darkgray
cylindreFullColor=green3-DarkGreen
cylindreFullColor2=green2-DarkGreen
cylindreOutColor=lime-Green4
texteColor=red


progressYmax=$(((imgYSize*95)/100)) 
progressYmin=$(((imgYSize*55)/100))
progressXmin=$(((imgXSize*5)/100))
progressXmax=$((imgXSize-progressXmin))
wc=$(((progressYmax-progressYmin)/4))
hc=$(((progressYmax-progressYmin)/2))
fontSize=$(((imgYSize*2)/5)) # 40%
fontShadow=firebrick3


imgYSizeOrigin=${imgYSize}
pct5=$(((imgYSize*5)/100))
((progressYmin=pct5/2))
imgYSize=$((imgYSize*45/100))
((progressYmax=imgYSize-progressYmin))

epaisseur=4

fillYmin=$((progressYmin+epaisseur))
fillYmax=$((progressYmax-epaisseur))
fillwc=$(((fillYmax-fillYmin)/4))
fillhc=$(((fillYmax-fillYmin)/2))
fillXmin=$((progressXmin+epaisseur))
fillXmax=$((${progressXmax}-2*wc+2*fillwc))

end()
{
#	[ -f "${resultat}" ] && rm "${resultat}"
	exit $1
}

makeIcon()
{ 
	texte="$1"
	pct=$2

	max=$((fillXmin+2*fillwc+pct*(fillXmax-2*fillwc-fillXmin)/100)); 
	((max<fillXmin+2*fillwc)) && max=$((fillXmin+2*fillwc))
	
	resultat=image.png
	
convert -size ${imgXSize}x${imgYSize} \( xc:none -stroke ${borderColor} \
   -tile gradient:${cylindreEmptyColor} \
                   -draw "roundrectangle ${progressXmin},${progressYmin},${progressXmax},${progressYmax} ${wc},${hc}" \
  -tile gradient:${cylindreFullColor} \
                   -draw "roundrectangle ${fillXmin},${fillYmin},${max},${fillYmax} ${fillwc},${fillhc}" \
  -tile gradient:${cylindreFullColor2} \
                   -draw "roundrectangle $((max-2*fillwc)),${fillYmin},${max},${fillYmax} ${fillwc},${fillhc}" \
    \) \
	\( xc:none -stroke ${borderColor} \
			-tile gradient:${cylindreOutColor} \
			-draw "roundrectangle ${fillXmin},${fillYmin},${max},${fillYmax} ${fillwc},${fillhc}" \
		\( xc:none -tile gradient:${cylindreInsideColor} \
				-draw "roundrectangle $((progressXmax-2*wc)),${progressYmin},${progressXmax},${progressYmax} ${wc},${hc}"  \) \
				-compose DstAtop -composite \) \
	-compose over -composite \
		-fill none -strokewidth 2 -stroke ${borderColor} -draw "roundrectangle ${progressXmin},${progressYmin},${progressXmax},${progressYmax} ${wc},${hc}" \
		\( +clone -background ${borderColor} -shadow 80x3+3+3 \) \
		+swap -background none -layers merge \
		\( xc:none -fill none -strokewidth 2 -draw "roundrectangle $((progressXmax-2*wc)),${progressYmin},${progressXmax},${progressYmax} ${wc},${hc}" \
			\( +clone -background ${borderColor} -shadow  80x3+3+3 \) \
			+swap -background none -layers merge \
		\) \
		-background none -layers merge \
	\( -font "${font}" -pointsize ${fontSize} \
		-strokewidth 1 -stroke ${fontShadow} -fill red label:"${texte}" -trim +repage  \
		\( +clone -background ${fontShadow} -shadow 80x3+3+3 \
		\) +swap -background none -layers merge \) \
	-insert 0 -gravity center -append \
	-background none -gravity center -extent ${imgXSize}x${imgYSizeOrigin} \
   "${resultat}"
	
	echo "icon:${resultat}"
	echo "tooltip:${texte}"
}

{
for ((x=50;x<=50;x++))
do
	makeIcon "${x} %" ${x}
done 
#makeIcon "OK !" 100
#read -s -n1
} | zenity --listen --notification --window-icon=info --text "0 %"

end 0
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: [SOLVED] Better way to produce this png ?

Post by anthony »

The lack of perspective is that the green cylinder is not quite at the 'end', and you can not see the complete ellipse of its top inside the glass tube. You must remember a cylinders length is from the center of the ellipse (or the top of the elliptical curve) and not from the bounds of the rounded rectangle being used to draw the ellipse. When the green ellipse is at 100 percent the centers of the ellipse should match.

Only the walls of the cylinder should have thickness not the ends. That is a hollow but open ended tube.

Also you will also need to draw the other right end of the glass tube, maybe with a slightly lighter color, or stroke thickness.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
Post Reply