Page 1 of 1

Beveled edges on a rectangle

Posted: Wed Jan 13, 2016 7:15 am
by Keya
my google for "bevel site:purebasic.fr" yielded only half a dozen results! :( and none particularly on target lol

Anyway here is my attempt. I only need it for rectangles, which is good as the thought of doing it with other shapes scares me :) I find it interesting how easy this is to do with rectangles, yet how its a bit trickier if it's a triangle or pentagon. Wonders of the universe!

First is a manual one-box-at-a-time, which looks good but its currently just black-to-white (anyone know how to do a fade from color-to-shadowcolor instead?). Also I discovered PB's gradient functions for a proper color-to-color transition (shown here) which is what id like the first one to do instead of black-to-white:
Image

Code: Select all

Procedure CreateBevelBoxBW(color, bevelwidth, width, height)
  Protected hImg, w, h, pct.f
  hImg = CreateImage(#PB_Any, width, height, 24, color) 
  If hImg
    If StartDrawing(ImageOutput(hImg))
      If bevelwidth > 0        
        DrawingMode(#PB_2DDrawing_Outlined)
        For i = 0 To bevelwidth-1
          pct = (i / bevelwidth-1) * 255
          FrontColor(RGB(pct,pct,pct))
          Box(0+i, 0+i, width-(i*2),height-(i*2))
        Next i        
      EndIf
      StopDrawing() 
    EndIf
    ProcedureReturn hImg
  EndIf
EndProcedure



Procedure CreateBevelBox(color, shadowcolor, bevelwidth, width, height)
  Protected hImg, w, h, pct.f
  hImg = CreateImage(#PB_Any, width, height, 24, color) 
  If hImg
    If StartDrawing(ImageOutput(hImg))
      If bevelwidth > 0        
        DrawingMode(#PB_2DDrawing_Gradient)
        GradientColor(0.0, color)
        GradientColor(1.0 - (bevelwidth*0.01), color)
        GradientColor(1.0, shadowcolor)
        BoxedGradient(0,0,width,height)
        Box(0,0,width,height)        
      EndIf
      StopDrawing() 
    EndIf
    ProcedureReturn hImg
  EndIf
EndProcedure



width = 400:  height = 200
color = RGB(0,200,200)
shadowcolor = RGB(0,0,50)
bevelwidth = 10

If OpenWindow(0, 0, 0, width, height, "Bevel box", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  
  hImg = CreateBevelBox(color, shadowcolor, bevelwidth, width, height)
  
  ;hImg = CreateBevelBoxBW(color, bevelwidth, width, height)
  
  
  If IsImage(hImg):  ImageGadget(0, 0, 0, width, height, ImageID(hImg)): EndIf
  Repeat
    Event = WaitWindowEvent()
  Until Event = #PB_Event_CloseWindow
EndIf

Re: Beveled edges on a rectangle

Posted: Mon Jan 18, 2016 10:15 pm
by Samuel
Keya wrote: First is a manual one-box-at-a-time, which looks good but its currently just black-to-white (anyone know how to do a fade from color-to-shadowcolor instead?).
You can calculate it by finding the difference between the inner and outer colors, and then divide those RGB values by the bevel length.

Here's a quick example.

Code: Select all

Procedure CreateBevelBox2(InnerColor.i, OuterColor.i, BevelWidth.i, Width.i, Height.i)
  
  Define.i Image
  Define.i CTR
  Define.i StartR, StartG, StartB
  Define.i R, G, B
  Define.i DifR, DifG, DifB
  Define.d PctR, PctG, PctB
  
  Image = CreateImage(#PB_Any, Width, Height, 24)
  
  R = Red(OuterColor)
  G = Green(OuterColor)
  B = Blue(OuterColor)
  
  DifR = Red(InnerColor) - Red(OuterColor)
  DifG = Green(InnerColor) - Green(OuterColor)
  DifB = Blue(InnerColor) - Blue(OuterColor)
  
  PctR = DifR / BevelWidth
  PctG = DifG / BevelWidth
  PctB = DifB / BevelWidth
  
  StartDrawing(ImageOutput(Image))
    For CTR = 0 To BevelWidth - 1
      R + PctR
      G + PctG
      B + PctB
      Box(CTR, CTR, Width-CTR*2, Height-CTR*2, RGB(R,G,B))
    Next
    Box(BevelWidth-1, BevelWidth-1, Width+2-BevelWidth*2, Height+2-BevelWidth*2, InnerColor)
  StopDrawing()
  
  ProcedureReturn Image
  
EndProcedure

width = 400
height = 200
bevelwidth = 10

If OpenWindow(0, 0, 0, width, height, "Bevel box", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
 
  hImg = CreateBevelBox2(RGB(255,0,0), RGB(0,50,50), bevelwidth, width, height)
 
  If IsImage(hImg)
    ImageGadget(0, 0, 0, width, height, ImageID(hImg))
  EndIf
  
  Repeat
    Event = WaitWindowEvent()
  Until Event = #PB_Event_CloseWindow
EndIf

Re: Beveled edges on a rectangle

Posted: Mon Jan 18, 2016 11:03 pm
by BasicallyPure
Hi Samuel,

I like your example.
I think it works better if you define R G B as double rather than integer. :)
Change bevelwidth to 30 to see the difference.

Code: Select all

;Define.i R, G, B
Define.d R, G, B

Re: Beveled edges on a rectangle

Posted: Tue Jan 19, 2016 4:58 am
by Keya
ahhh, thanks Samuel! :)
Also i just found this neat little procedure by thyphoon which he uses in a password strength meter to indicate from green-to-red http://www.purebasic.fr/english/viewtopic.php?p=254452

Code: Select all

Procedure GetColor(ColorA.l, ColorB.l, Min.l, Max.l, Cursor.l)
  Protected R.l, G.l, B.l
  Max = Max-Min
  Cursor = Cursor-Min
  R = Red(ColorB)-Red(ColorA)
  R = Red(ColorA) + (R*Cursor/Max)
  G = Green(ColorB)-Green(ColorA)
  G = Green(ColorA) + (G*Cursor/Max)
  B = Blue(ColorB)-Blue(ColorA)
  B = Blue(ColorA) + (B*Cursor/Max)
  ProcedureReturn RGB(R, G, B)
EndProcedure
eg. MiddleColor = GetColor(RGB(255,0,0), RGB(0,255,0), 0, 255, 128)

Re: Beveled edges on a rectangle

Posted: Wed Jan 20, 2016 3:40 am
by PureLust
Hi Keya,

maybe you want to bevel some images sometime, or want to create sharper or softener bevel
or even buttons with flipping bevel, so this little routine might be helpful.


Image

Code: Select all

EnableExplicit

Procedure BevelImage(ImageNr, BevelSize, HighlightColor=#White, ShadowColor=#Black, MinOpacity=30, MaxOpacity=180)
	Protected Alpha.c, n
	Protected r1=Red(HighlightColor), g1=Green(HighlightColor), b1=Blue(HighlightColor)
	Protected r2=Red(ShadowColor), g2=Green(ShadowColor), b2=Blue(ShadowColor)
	
	If IsImage(ImageNr)
		
		Protected Width  = ImageWidth(ImageNr)
		Protected Height = ImageHeight(ImageNr)
		
		Protected Dummy = CreateImage(#PB_Any, Width, Height, 32, #PB_Image_Transparent)
		
		If BevelSize > 0 And Width > 2 * BevelSize And Height > 2 * BevelSize
			If Dummy And StartDrawing(ImageOutput(Dummy))
				
				DrawingMode(#PB_2DDrawing_AllChannels)
				
				For n = 0 To BevelSize-1
					
					Alpha = MaxOpacity - (((MaxOpacity-MinOpacity) * n) / (BevelSize-1))
					
					Line(n,n, Width-2*n, 1, RGBA(r1,g1,b1,Alpha))
					Line(n,n, 1, Height-2*n, RGBA(r1,g1,b1,Alpha))
					Line(n+1,Height-n-1, Width-2*n, 1, RGBA(r2,g2,b2,Alpha))
					Line(Width-n-1,n+1, 1, Height-2*n, RGBA(r2,g2,b2,Alpha))
					
				Next
				
				StopDrawing()
				
				If StartDrawing(ImageOutput(ImageNr))
					DrawingMode(#PB_2DDrawing_AlphaBlend)
					DrawImage(ImageID(Dummy),0,0)
					StopDrawing()
					ProcedureReturn #True
				EndIf
				
			EndIf
		EndIf
	EndIf
EndProcedure



Define Width = 200,  Height = 150, n, Event

; ----- creating some rectangular Images -----

Define Img1 = CreateImage(#PB_Any, Width, Height, 24, $ff6666)
Define Img2 = CreateImage(#PB_Any, Width, Height, 24, $66ff66)
Define Img3 = CreateImage(#PB_Any, Width, Height, 24, $6666ff)
Define Img4 = CreateImage(#PB_Any, Width, Height, 24, $008888)

If StartDrawing(ImageOutput(Img4))			; ----- let's paint some circles ...
	For n = 1 To 200
		Circle(Random(Width), Random(Height), 30, Random($ffffff))
	Next
	StopDrawing()
EndIf

Define Img5 = CopyImage(Img1, #PB_Any)	; ----- clone the Images for click-beveling
Define Img6 = CopyImage(Img2, #PB_Any)
Define Img7 = CopyImage(Img3, #PB_Any)
Define Img8 = CopyImage(Img4, #PB_Any)

; -----  beveling Button-Images -----

BevelImage(Img1, 10)
BevelImage(Img2, 30, #Yellow, $008800, 0, 255)
BevelImage(Img3, 15, #White, #Black, 50, 90)
BevelImage(Img4, 20, #White, #Black, 0, 255)

; -----  beveling clicked Button-Images -----

BevelImage(Img5, 10, #Black, #White)
BevelImage(Img6, 20, #Yellow, $008800, 0, 160)
BevelImage(Img7, 15, #Black, #White,90,90)
BevelImage(Img8, 20, #Black, #White, 0, 190)

Width + 8
Height + 8

If OpenWindow(0, 0, 0, Width * 2 + 30, Height * 2 + 30, "BevelImage() - Example", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
	
	ButtonImageGadget(0, 10,10,Width,Height, ImageID(Img1))
	ButtonImageGadget(1, 20+Width,10,Width,Height, ImageID(Img2))
	ButtonImageGadget(2, 10,20+Height,Width,Height, ImageID(Img3))
	ButtonImageGadget(3, 20+Width,20+Height,Width,Height, ImageID(Img4))
	
	SetGadgetAttribute(0, #PB_Button_PressedImage, ImageID(Img5))
	SetGadgetAttribute(1, #PB_Button_PressedImage, ImageID(Img6))
	SetGadgetAttribute(2, #PB_Button_PressedImage, ImageID(Img7))
	SetGadgetAttribute(3, #PB_Button_PressedImage, ImageID(Img8))
	
	Repeat
		Event = WaitWindowEvent()
	Until Event = #PB_Event_CloseWindow
EndIf

Re: Beveled edges on a rectangle

Posted: Wed Jan 20, 2016 10:00 am
by Keya
PureLust, really nice! thankyou :) you're off by 1 pixel in the lower-left corner however! Easiest seen in your green-yellow button example. I had a quick go at fixing it but just kept making it worse lol
Image

Re: Beveled edges on a rectangle

Posted: Fri Jan 22, 2016 3:32 pm
by PureLust
Keya wrote:PureLust, really nice! thankyou :) you're off by 1 pixel in the lower-left corner however!
Hey Keya, ... yes, you were right.

Just corrected the code in my post above. :wink:

Re: Beveled edges on a rectangle

Posted: Fri Jan 22, 2016 4:43 pm
by walbus
Very nice idea !