Opération sur les Fonts

Programmation d'applications complexes
Avatar de l’utilisateur
graph100
Messages : 1318
Inscription : sam. 21/mai/2005 17:50

Opération sur les Fonts

Message par graph100 »

Un projet que j'ai en tête depuis un long moment m'amène à me coltiner avec les FONTs et l'affichage graphique de texte.
Le but lointain est de parvenir rajouter une surcouche sur des images, permettant d'afficher le texte des bulles dans plusieurs langages, et de la façon la plus libre possible.

Il faut donc pouvoir manipuler l'affichage d'un texte, pour avoir au final performance / qualité / le moins de contrainte de mise en forme possible.

Or je suis très mécontent de la fonction DrawRotatedText(). Le résultat n'est pas constant, elle n'est pas souple, les fonctions TextWidth() et TextHeight() ne donnent pas les bonnes distances exactement.
Au fil de la mise en place de ce que j'ai en tête, je suis parvenu à dessiner un texte avec l'angle voulus pour n'importe quelle police.
Maintenant il reste les effets à mettre en place.

Donc, à votre avis, comment procéder pour obtenir le résultat suivant :

Image

Ce qui m'intéresse c'est de pouvoir dessiner le contour d'un texte, quel qu'il soit (en fonction de la police chargée), avec une taille de font de 12 tout autant que pour du 80 !
_________________________________________________
Mon site : CeriseCode (Attention Chantier perpétuel ;))
Avatar de l’utilisateur
kernadec
Messages : 1594
Inscription : ven. 25/avr./2008 11:14

Re: Opération sur les Fonts

Message par kernadec »

Bonjour Graph100

peut être avec deux tailles de fonte
exemple: une fonte de 14 en noir et par-dessus une fonte de 12 blanche
ça devrait fonctionner et avoir une fonte de 13 :D

[réédit] j'ai dis un truc idiot, après essai avec deux tailles de fonte cela n'est pas possible,
Mais avec un texte superposé et la fonction DrawingMode() c'est possible, voir code suivant.

cordialement
Dernière modification par kernadec le ven. 21/mars/2014 12:36, modifié 1 fois.
Avatar de l’utilisateur
kernadec
Messages : 1594
Inscription : ven. 25/avr./2008 11:14

Re: Opération sur les Fonts

Message par kernadec »

test avec un source modifié de danilo (codearchive)

Désolé ce n'est pas top :(

Cordialement

Code : Tout sélectionner

; English forum: 
; Author: Danilo (updated for PB4.00 by blbltheworm)
; Date: 11. November 2002
; OS: Windows
; Demo: No


; Cool Fonts 1, by Danilo - 11.11.2002
;
#FONT_NORMAL    = %00000000
#FONT_BOLD      = %00000001
#FONT_ITALIC    = %00000010
#FONT_UNDERLINE = %00000100
#FONT_STRIKEOUT = %00001000


Procedure CreateFont(Name$,Size,Style)
  If (Style & #FONT_BOLD)      : bold = 700    : EndIf
  If (Style & #FONT_ITALIC)    : italic = 1    : EndIf
  If (Style & #FONT_UNDERLINE) : underline = 1 : EndIf
  If (Style & #FONT_STRIKEOUT) : strikeout = 1 : EndIf
  ProcedureReturn CreateFont_(Size,0,0,0,bold,italic,underline,strikeout,0,0,0,0,0,Name$)
EndProcedure

Procedure CreateMyImage()
  Normal    = CreateFont("Verdana",48,#FONT_NORMAL)
  bold      = CreateFont("Script MT Bold",48,#FONT_BOLD)
  italic    = CreateFont("Verdana",48,#FONT_ITALIC)
  underline = CreateFont("Verdana",48,#FONT_UNDERLINE)
  strikeout = CreateFont("Verdana",48,#FONT_STRIKEOUT)
  Combined1 = CreateFont("Verdana",48,#FONT_BOLD|#FONT_UNDERLINE)
  Combined2 = CreateFont("Verdana",48,#FONT_ITALIC|#FONT_UNDERLINE|#FONT_STRIKEOUT|#FONT_BOLD)
  
  image = CreateImage(1,600,400)
  StartDrawing(ImageOutput(1))
  DrawingMode(1)
  
  Box(0,0,600,400, RGB($ff,$ff,$ff))  ; fond blanc
  
  FrontColor(RGB($00,$00,$00))
  
  ;         DrawingFont(Normal)
  ;         DrawText(10,10,"PureBasic - normal")
  DrawingFont(bold)
  DrawText(10,60,"PureBasic - Bold")
  ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++         
  DrawingFont(bold)
  DrawingMode(2)
  FrontColor(RGB($ff,$ff,$ff))
  DrawText(11,61,"PureBasic - Bold")
  FrontColor(RGB($00,$00,$00))
  ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++        
  ;         DrawingMode(1)
  ;         DrawingFont(italic)
  ;         DrawText(10,110,"PureBasic - Italic")
  ;         DrawingFont(Underline)
  ;         DrawText(10,160,"PureBasic - Underline")
  ;         DrawingFont(StrikeOut)
  ;         DrawText(10,210,"PureBasic - StrikeOut")
  ;         DrawingFont(Combined1)
  ;         DrawText(10,260,"PureBasic - Combined 1")
  ;         DrawingFont(Combined2)
  ;         DrawText(10,310,"PureBasic - Combined 2")
  StopDrawing()
  
  DeleteObject_(Normal)   : DeleteObject_(Bold)
  DeleteObject_(Italic)   : DeleteObject_(Underline)
  DeleteObject_(StrikeOut): DeleteObject_(Combined1)
  DeleteObject_(Combined2)
  
  ProcedureReturn image
EndProcedure

OpenWindow(1,100,200,600,400,"Cool Fonts 1",#PB_Window_SystemMenu)


myImage = CreateMyImage()

CreateGadgetList(WindowID(1))
ImageGadget(1,0,0,600,400,myImage)

Repeat:Until WaitWindowEvent() = #PB_Event_CloseWindow
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Re: Opération sur les Fonts

Message par djes »

Tu pourrais faire un traitement d'image avec une mise en valeur du contour (voir http://www.purebasic.fr/english/viewtop ... ead#unread), ou plutôt regarder du côté de GDI+ qui contient quelques fonctions assez poussées pour le texte :
http://www.purebasic.fr/english/viewtop ... it=drawing
http://purebasic.developpez.com/tutoriels/gdi/#LV-
http://bobpowell.net/texteffects.aspx
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Re: Opération sur les Fonts

Message par Backup »

Cederavic pour "Barbouille"
m'avait fait une fonction qui ressort les contours

http://www.purebasic.fr/french/viewtopi ... e&start=90

regarde la procedure getEdgeGray(x, y, Array image_tab(2), alternate = #False) :)
Avatar de l’utilisateur
graph100
Messages : 1318
Inscription : sam. 21/mai/2005 17:50

Re: Opération sur les Fonts

Message par graph100 »

Merci ! J'y jette un œil de suite.
_________________________________________________
Mon site : CeriseCode (Attention Chantier perpétuel ;))
Avatar de l’utilisateur
graph100
Messages : 1318
Inscription : sam. 21/mai/2005 17:50

Re: Opération sur les Fonts

Message par graph100 »

Les fonctions de la suite GDI+ sont vraiment sympas, mais limité à windows...

Sinon, en adaptant la fonction getEdge() de manière à cadrer avec mes limitations, je suis parvenu à accélérer le traitement d'une surface de 400x400 de 780ms à 65ms (sur mon ordi)
et obtenir une détection satisfaisante du tour de la police.

Code : Tout sélectionner

;{ procedure

Procedure GetEdgeGray(Array image_tab.a(2))
	
	w = ArraySize(image_tab(), 1) - 1
	h = ArraySize(image_tab(), 2) - 1
	
	For x = 1 To w
		For y = 1 To h
			
			deltaX.l = (image_tab(x + 1, y - 1) + image_tab(x + 1, y) << 1 + image_tab(x + 1, y + 1)) - (image_tab(x - 1, y - 1)   + image_tab(x - 1, y) << 1 + image_tab(x - 1, y + 1))
			deltaY.l = (image_tab(x - 1, y - 1)  + image_tab(x, y - 1) << 1    + image_tab(x + 1, y - 1)  ) - (image_tab(x - 1, y + 1) + image_tab(x, y + 1) << 1 + image_tab(x + 1, y + 1))
			
			gray.l = Sqr(deltaX * deltaX + deltaY * deltaY)
			
			If image_tab(x, y) <> 0
				gray = 255 - image_tab(x, y)
			Else
				If gray > 255
					gray = 255
				ElseIf gray < 0
					gray = 0
				EndIf
			EndIf
			
			Plot(x, y, RGB(gray, gray, gray))
		Next
	Next
	
	ProcedureReturn gray
EndProcedure

;}


;{ fenetre

OpenWindow(0, 0, 0, 800, 600, "", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)

CanvasGadget(0, 0, 0, WindowWidth(0), WindowHeight(0), #PB_Canvas_Keyboard)

;}

;{ load image

w = 400
h = 400
CreateImage(0, w+1, h+1)

Dim font(10)

For i = 0 To 10
	font(i) = LoadFont(#PB_Any, "Arial", i * 2 + 4)
Next

StartDrawing(ImageOutput(0))

y = 5
For i = 0 To 10
	DrawingFont(FontID(font(i)))
	DrawText(20, 5 + y, "Ceci est un TEST !", #White)
	
	y = y + 1 + TextHeight(" ")
Next

Dim image.a(w+1, h+1)

For x = 1 To w
	For y = 1 To h
		c = Point(x, y)
		image(x, y) = (Red(c) + Green(c) + Blue(c)) / 3
	Next
Next

StopDrawing()

;}

DRAW_Police = 1
REDRAW = #True


;{ boucle principale

Repeat
	event = WaitWindowEvent()
	
	;{ event
	
	If event = #PB_Event_Gadget
		If EventGadget() = 0
			If EventType() = #PB_EventType_KeyUp
				Select GetGadgetAttribute(0, #PB_Canvas_Key)
						Case #PB_Shortcut_Escape
							event = #PB_Event_CloseWindow
							
						Case #PB_Shortcut_Space
							REDRAW = #True
							
							DRAW_Police = -DRAW_Police
							
				EndSelect
			EndIf
		EndIf
	EndIf
	
	;}
	
	;{ dessin
	
	If REDRAW
		StartDrawing(CanvasOutput(0))
		
		Box(0, 0, OutputWidth(), OutputHeight(), 0)
		
		time = ElapsedMilliseconds()
		
		GetEdgeGray(image())
		
		time = ElapsedMilliseconds() - time
		
		
		DrawText(10, OutputHeight() - 20, Str(time) + " ms")
		DrawText(10, OutputHeight() - 40, "ESPACE pour remplir ou non le Texte")
		
		
		If DRAW_Police = 1
			DrawingMode(#PB_2DDrawing_Transparent)
			y = 5
			For i = 0 To 10
				DrawingFont(FontID(font(i)))
				DrawText(20, 5 + y, "Ceci est un TEST !", #Red)
				
				y = y + 1 + TextHeight(" ")
			Next
		EndIf
		
		StopDrawing()
		REDRAW = #False
	EndIf
	
	;}
	
Until event = #PB_Event_CloseWindow


;}


End
L'étape suivante est le réglage de l'épaisseur de ce contour.
_________________________________________________
Mon site : CeriseCode (Attention Chantier perpétuel ;))
Avatar de l’utilisateur
graph100
Messages : 1318
Inscription : sam. 21/mai/2005 17:50

Re: Opération sur les Fonts

Message par graph100 »

Avec l'épaisseur :

Code : Tout sélectionner

;{ procedure

Procedure GetEdgeGray(Array image.a(2), rayon = 1)
	
	w = ArraySize(image(), 1) - 1
	h = ArraySize(image(), 2) - 1
	
	Dim image_save.a(w + 1, h + 1)
	Dim image_tab.a(w + 1, h + 1)
	Dim image_tab2.a(w + 1, h + 1)
	
	CopyArray(image(), image_tab2())
	
 	For i = 1 To rayon
		CopyArray(image_tab2(), image_tab())
		
		For x = 1 To w
			For y = 1 To h
				
				If image_tab(x, y) < 255
					deltaX_.l = (image_tab(x + 1, y - 1) + image_tab(x + 1, y) << 1 + image_tab(x + 1, y + 1)) - (image_tab(x - 1, y - 1)   + image_tab(x - 1, y) << 1 + image_tab(x - 1, y + 1))
					deltaY_.l = (image_tab(x - 1, y - 1)  + image_tab(x, y - 1) << 1    + image_tab(x + 1, y - 1)  ) - (image_tab(x - 1, y + 1) + image_tab(x, y + 1) << 1 + image_tab(x + 1, y + 1))
					
					deltaX.d = deltaX_ / 3
					deltaY.d = deltaY_ / 3
					
					gray.l = Sqr(deltaX * deltaX + deltaY * deltaY)
					
					If gray > 0
						
						If image_tab(x, y) > 0
							gray = 255 - image(x, y)
						Else
							If gray > 255
								gray = 255
							EndIf
						EndIf
						
						
						image_tab2(x, y) = gray
						
						Plot(x, y, RGB(gray, gray, gray))
						image_save(x, y) = gray
					EndIf
				EndIf
			Next
		Next
		
	Next
EndProcedure

;}


;{ fenetre

OpenWindow(0, 0, 0, 800, 600, "ARRAY", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)

CanvasGadget(0, 0, 0, WindowWidth(0), WindowHeight(0), #PB_Canvas_Keyboard)
SetActiveGadget(0)
;}

;{ load image

w = 800
h = 400

nb_font = 14

CreateImage(0, w+1, h+1)

Dim font(nb_font)

For i = 0 To nb_font
	font(i) = LoadFont(#PB_Any, "Arial", i * 2 + 4)
Next

StartDrawing(ImageOutput(0))

y = 5
For i = 0 To nb_font
	DrawingFont(FontID(font(i)))
	DrawText(20, 5 + y, "Ceci est un TEST !", #White)
	
	y = y + 1 + TextHeight(" ")
Next

Dim image.a(w+1, h+1)
Dim image2.a(w+1, h+1)

For x = 1 To w
	For y = 1 To h
		c = Point(x, y)
		image(x, y) = (Red(c) + Green(c) + Blue(c)) / 3
	Next
Next

StopDrawing()



;}

DRAW_Police = 1
REDRAW = #True
rayon = 3


;{ boucle principale

Repeat
	event = WaitWindowEvent()
	
	;{ event
	
	If event = #PB_Event_Gadget
		If EventGadget() = 0
			If EventType() = #PB_EventType_KeyDown
				Select GetGadgetAttribute(0, #PB_Canvas_Key)
					Case #PB_Shortcut_Escape
						event = #PB_Event_CloseWindow
						
					Case #PB_Shortcut_Space
						REDRAW = #True
						
						DRAW_Police = -DRAW_Police
						
					Case #PB_Shortcut_Up
						REDRAW = #True
						
						rayon + 1
						If rayon > 10 : rayon = 10 : EndIf
						
					Case #PB_Shortcut_Down
						REDRAW = #True
						
						rayon - 1
						If rayon < 1 : rayon = 1 : EndIf
						
				EndSelect
			EndIf
		EndIf
	EndIf
	
	;}
	
	;{ dessin
	
	If REDRAW
		StartDrawing(CanvasOutput(0))
		
		Box(0, 0, OutputWidth(), OutputHeight(), #Blue)
		
		time = ElapsedMilliseconds()
		GetEdgeGray(image(), rayon)
		time = ElapsedMilliseconds() - time
		
		
		DrawText(10, OutputHeight() - 20, Str(time) + " ms")
		DrawText(10, OutputHeight() - 40, "ESPACE pour remplir ou non le Texte")
		DrawText(10, OutputHeight() - 60, "Up / Down pour faire varier le rayon (r = " + Str(rayon) + ")")
		
		Line(0, h, w, 1, 0)
		Line(w, 0, 1, h, 0)
		
		If DRAW_Police = 1
			DrawingMode(#PB_2DDrawing_Transparent)
			y = 5
			For i = 0 To nb_font
				DrawingFont(FontID(font(i)))
				DrawText(20, 5 + y, "Ceci est un TEST !", #Red)
				
				y = y + 1 + TextHeight(" ")
			Next
		EndIf
		
		StopDrawing()
		REDRAW = #False
	EndIf
	
	;}
	
Until event = #PB_Event_CloseWindow


;}


End
Le problème de ce code est qu'il parcourt plusieurs fois le tableau. Plus le rayon est grand, plus c'est lent !
Dernière modification par graph100 le sam. 22/mars/2014 0:35, modifié 1 fois.
_________________________________________________
Mon site : CeriseCode (Attention Chantier perpétuel ;))
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Re: Opération sur les Fonts

Message par Backup »

peut etre plus simplement remplacer

Code : Tout sélectionner

  Plot(x, y, RGB(gray, gray, gray))
par un Circle ... avec le rayon qui fait la taille non ?
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

Re: Opération sur les Fonts

Message par nico »

Marche très bien chez moi.

C'est plus doux avec ces modifications:

Ligne 157:
DrawingMode(#PB_2DDrawing_Transparent | #PB_2DDrawing_AlphaClip )
GetEdgeGray(image(), rayon)

Ligne 47:
Plot(x, y, RGBA(gray, gray, gray, 180 ))
Avatar de l’utilisateur
graph100
Messages : 1318
Inscription : sam. 21/mai/2005 17:50

Re: Opération sur les Fonts

Message par graph100 »

Dobro a écrit :peut etre plus simplement remplacer

Code : Tout sélectionner

  Plot(x, y, RGB(gray, gray, gray))
par un Circle ... avec le rayon qui fait la taille non ?
Ça donne un effet vraiment bizarre ! Mais ce qui m'intéresse est de récupérer le tableau de point, et non l'image. Le rendu graphique est effectué ensuite en fonction d'un angle.

@nico : j'ai essayé, mais le résultat est étrange pour un fond autre que noir, ça laisse des artefacts de partout :lol:
et enfin, comme ce que j'ai dis pour Dobro, c'est le tableau de point qui est le rendu voulu.

Ensuite ce tableau est utilisé dans des opérations de rotation et composition avec les couleurs de police / contour / fond, etc...
_________________________________________________
Mon site : CeriseCode (Attention Chantier perpétuel ;))
Avatar de l’utilisateur
graph100
Messages : 1318
Inscription : sam. 21/mai/2005 17:50

Re: Opération sur les Fonts

Message par graph100 »

Le même résultat en passant par une liste chainée.
L'exécution est bien plus rapide pour les grandes images, et un grand rayon (en comparaison avec la méthode Array)

J'en ai profité pour ajouter la rotation antialisée (Merci Luis !)

Code : Tout sélectionner

;{ procedure

Procedure GetEdgeGray(Array image.a(2), rayon = 1)
	w = ArraySize(image(), 1) - 1
	h = ArraySize(image(), 2) - 1
	
	Dim image_save.a(w + 1, h + 1)
	Dim image_tab.a(w + 1, h + 1)
	Dim image_tab2.a(w + 1, h + 1)
	
	Dim *adr.POINT(w + 1, h + 1)
	
	CopyArray(image(), image_tab2())
	
	NewList coord.POINT()
	NewList new_coord.POINT()
	
	Macro AjoutPoint(_x_, _y_)
		If *adr(_x_, _y_) = 0 And image_tab(_x_, _y_) = 0 And _x_ < w + 1 And _y_ < h + 1 And _x_ > 0 And _y_ > 0
			AddElement(new_coord())
			
			*adr(_x_, _y_) = @new_coord()
			new_coord()\x = _x_
			new_coord()\y = _y_
		EndIf
	EndMacro
	
	CopyArray(image(), image_tab())
	
	;{ init
	For x = 1 To w
		For y = 1 To h
			
			If image_tab(x, y) < 255
				deltaX_.l = (image_tab(x + 1, y - 1) + image_tab(x + 1, y) << 1 + image_tab(x + 1, y + 1)) - (image_tab(x - 1, y - 1)   + image_tab(x - 1, y) << 1 + image_tab(x - 1, y + 1))
				deltaY_.l = (image_tab(x - 1, y - 1)  + image_tab(x, y - 1) << 1    + image_tab(x + 1, y - 1)  ) - (image_tab(x - 1, y + 1) + image_tab(x, y + 1) << 1 + image_tab(x + 1, y + 1))
				
				deltaX.d = deltaX_ / 3
				deltaY.d = deltaY_ / 3
				
				gray.l = Sqr(deltaX * deltaX + deltaY * deltaY)
				
				If gray > 0 Or image_tab(x, y) > 0
					
					If image_tab(x, y) > 0
						gray = 255 - image_tab(x, y)
					ElseIf gray > 255
						gray = 255
					EndIf
					
					image_tab2(x, y) = gray
					
					;{ ajout des points futurs
					
					If *adr(x, y) <> 0
						ChangeCurrentElement(new_coord(), *adr(x, y))
						DeleteElement(new_coord())
						*adr(x, y) = -1
					EndIf
					
					AjoutPoint(x+1, y)
					AjoutPoint(x, y+1)
					AjoutPoint(x-1, y)
					AjoutPoint(x, y-1)
					
					AjoutPoint(x+1, y+1)
					AjoutPoint(x+1, y-1)
					AjoutPoint(x-1, y+1)
					AjoutPoint(x-1, y-1)
					
					;}
					
					If rayon > 1
						image_save(x, y) = 255-image_tab(x, y)
					Else
						image_save(x, y) = gray
					EndIf
					
					;Plot(x, y, RGB(image_save(x, y), image_save(x, y), image_save(x, y)))
				EndIf
			EndIf
		Next
	Next
	;}
	
	;{ boucle normale
	For i = 2 To rayon
		CopyList(new_coord(), coord())
		CopyArray(image_tab2(), image_tab())
		
		Dim *adr.POINT(w + 1, h + 1)
		
		ClearList(new_coord())
		
		ForEach coord()
			x = coord()\x
			y = coord()\y
			
			If image_save(x, y) < 255
				deltaX_.l = (image_tab(x + 1, y - 1) + image_tab(x + 1, y) << 1 + image_tab(x + 1, y + 1)) - (image_tab(x - 1, y - 1)   + image_tab(x - 1, y) << 1 + image_tab(x - 1, y + 1))
				deltaY_.l = (image_tab(x - 1, y - 1)  + image_tab(x, y - 1) << 1    + image_tab(x + 1, y - 1)  ) - (image_tab(x - 1, y + 1) + image_tab(x, y + 1) << 1 + image_tab(x + 1, y + 1))
				
				deltaX.d = deltaX_ / 3
				deltaY.d = deltaY_ / 3
				
				gray.l = Sqr(deltaX * deltaX + deltaY * deltaY)
				
				If gray > 0 Or image_save(x, y) > 0
					
					If image_tab(x, y) > 0
						gray = 255 - image(x, y)
					ElseIf gray > 255
						gray = 255
					EndIf
					
					image_tab2(x, y) = gray
					
					;{ ajout des points futurs
					
					If *adr(x, y) <> 0
						ChangeCurrentElement(new_coord(), *adr(x, y))
						DeleteElement(new_coord())
						*adr(x, y) = -1
					EndIf
					
					AjoutPoint(x+1, y)
					AjoutPoint(x, y+1)
					AjoutPoint(x-1, y)
					AjoutPoint(x, y-1)
					
					AjoutPoint(x+1, y+1)
					AjoutPoint(x+1, y-1)
					AjoutPoint(x-1, y+1)
					AjoutPoint(x-1, y-1)
					
					;}
					
					If i < rayon
						image_save(x, y) = 255
					Else
						image_save(x, y) = gray
					EndIf
					
					;Plot(x, y, RGB(image_save(x, y), image_save(x, y), image_save(x, y)))
					
				EndIf
			EndIf
		Next
	Next
	;}
	
	CopyArray(image_save(), image())
EndProcedure

Procedure DrawRotatedArrayGray(Array image.a(2), centre_x, centre_y, x, y, Angle.d, couleur.l, Antialiasing = #True)
	Protected.d Angle_Cos, Angle_Sin
	Protected.l w, h, iXc1, iYc1, iXc2, iYc2, iXs, iYs
	
	x - 1
	y - 1
	
	red.d = Red(Couleur) / 255
	green.d = Green(Couleur) / 255
	blue.d = Blue(Couleur) / 255
	
	x_max.l = OutputWidth() - 1
	y_max.l = OutputHeight() - 1
	
	Angle_Cos = Cos(Angle)
	Angle_Sin = Sin(Angle)
	
	w_source = ArraySize(image(), 1) ;- 1
	h_source = ArraySize(image(), 2) ;- 1
	
	w = Int(w_source * Abs(Angle_Cos) + h_source * Abs(Angle_Sin))
	h = Int(h_source * Abs(Angle_Cos) + w_source * Abs(Angle_Sin))
	
	iXc1 = w_source >> 1
	iYc1 = h_source >> 1
	iXc2 = w >> 1
	iYc2 = h >> 1
	
	c.d = x + iXc1
	d.d = y + iYc1
	new_angle.d = ATan2(c, d) + Angle; * #PI / 180
	dist.d = Sqr(c * c + d * d)
	
	c = centre_x + dist * Cos(new_angle) - iXc2
	d = centre_y + dist * Sin(new_angle) - iYc2
	
	Select Antialiasing
		Case #False
			For iY = 0 To h - 1
				For iX = 0 To w - 1
					
					; For each nDestImage point find rotated nSrcImage source point
					iXs = iXc1 + (iX - iXc2) * Angle_Cos + (iY - iYc2) * Angle_Sin
					iYs = iYc1 + (iY - iYc2) * Angle_Cos - (iX - iXc2) * Angle_Sin
					
					If iXs >= 0 And iXs < w_source  And iYs >= 0 And iYs < h_source
						a = c + iX
						b = d + iY
						
						If a >= 0 And a < x_max And b >= 0 And b < y_max
							color.l = Point(a, b)
							tmp.a = 255 - image(iXs, iYs)
							
							; Plot(a, b, RGB(image(iXs, iYs) * red, image(iXs, iYs) * green, image(iXs, iYs) * blue))
							Plot(a, b, RGB(image(iXs, iYs) * red + tmp * Red(color) / 255, image(iXs, iYs) * green + tmp * Green(color) / 255, image(iXs, iYs) * blue + tmp * Blue(color) / 255))
						EndIf
					EndIf
				Next
			Next
			
		Case #True
			
			For iY = 0 To h - 1
				For iX = 0 To w - 1
					
					; For each nDestImage point find rotated nSrcImage source point
					fXs.d = iXc1 + (iX - iXc2) * Angle_Cos + (iY - iYc2) * Angle_Sin
					fYs.d = iYc1 + (iY - iYc2) * Angle_Cos - (iX - iXc2) * Angle_Sin
					
					; 					iXs0 = Int(fXs) ; Strange behaviour when pixel have color for fXs, fYs near 0
					; 					iYs0 = Int(fYs)
					iXs0 = Round(fXs, #PB_Round_Down)
					iYs0 = Round(fYs, #PB_Round_Down)
					
					If iXs0 >= 0 And iXs0 < w_source - 1  And iYs0 >= 0 And iYs0 < h_source - 1
						a = c + iX
						b = d + iY
						
						If a >= 0 And a < x_max And b >= 0 And b < y_max
							
							; Bottom left coords of bounding floating point rectangle on nSrcImage
							
							fXfs1.d = fXs - Int(fXs)
							fYfs1.d = fYs - Int(fYs)
							
							fXfs1less.d = 1 - fXfs1 - 0.000005 : If fXfs1less < 0 : fXfs1less = 0 : EndIf
							fYfs1less.d = 1 - fYfs1 - 0.000005 : If fYfs1less < 0 : fYfs1less = 0 : EndIf
							
							ic0.d = image(iXs0 + 1, iYs0) * fXfs1 + image(iXs0, iYs0) * fXfs1less
							ic1.d = image(iXs0 + 1, iYs0 + 1) * fXfs1 + image(iXs0, iYs0 + 1) * fXfs1less
							
							; Weight along axis Y
							ic = fYfs1less * ic0 + fYfs1 * ic1
							
							
							color.l = Point(a, b)
							tmp.a = 255 - ic
							Plot(a, b, RGB(ic * red + tmp * Red(color) / 255, ic * green + tmp * Green(color) / 255, ic * blue + tmp * Blue(color) / 255))
						EndIf
					ElseIf iXs0 = w_source - 1  And iYs0 >= 0 And iYs0 < h_source - 1
						a = c + iX
						b = d + iY
						
						If a >= 0 And a < x_max And b >= 0 And b < y_max
							
							; Bottom left coords of bounding floating point rectangle on nSrcImage
							
							fXfs1.d = fXs - Int(fXs)
							fYfs1.d = fYs - Int(fYs)
							
							fXfs1less.d = 1 - fXfs1 - 0.000005 : If fXfs1less < 0 : fXfs1less = 0 : EndIf
							fYfs1less.d = 1 - fYfs1 - 0.000005 : If fYfs1less < 0 : fYfs1less = 0 : EndIf
							
							ic0.d = image(iXs0, iYs0) * fXfs1less
							ic1.d = image(iXs0, iYs0 + 1) * fXfs1less
							
							; Weight along axis Y
							ic = fYfs1less * ic0 + fYfs1 * ic1
							
							
							color.l = Point(a, b)
							tmp.a = 255 - ic
							Plot(a, b, RGB(ic * red + tmp * Red(color) / 255, ic * green + tmp * Green(color) / 255, ic * blue + tmp * Blue(color) / 255))
						EndIf
					ElseIf iXs0 >= 0 And iXs0 < w_source - 1 And iYs0 = h_source - 1
						a = c + iX
						b = d + iY
						
						If a >= 0 And a < x_max And b >= 0 And b < y_max
							
							; Bottom left coords of bounding floating point rectangle on nSrcImage
							
							fXfs1.d = fXs - Int(fXs)
							
							fXfs1less.d = 1 - fXfs1 - 0.000005 : If fXfs1less < 0 : fXfs1less = 0 : EndIf
							fYfs1less.d = 1 - fYfs1 - 0.000005 : If fYfs1less < 0 : fYfs1less = 0 : EndIf
							
							ic0.d = image(iXs0 + 1, iYs0) * fXfs1 + image(iXs0, iYs0) * fXfs1less

							
							; Weight along axis Y
							ic = fYfs1less * ic0
							
							
							color.l = Point(a, b)
							tmp.a = 255 - ic
							Plot(a, b, RGB(ic * red + tmp * Red(color) / 255, ic * green + tmp * Green(color) / 255, ic * blue + tmp * Blue(color) / 255))
						EndIf
					EndIf           
				Next
			Next
			
	EndSelect
	
	
EndProcedure


;}


;{ fenetre

OpenWindow(0, 0, 0, 800, 600, "LIST", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)

CanvasGadget(0, 0, 0, WindowWidth(0), WindowHeight(0), #PB_Canvas_Keyboard)
SetActiveGadget(0)
;}

;{ load image

w = 800
h = 400

nb_font = 14

CreateImage(0, w+1, h+1)

Dim font(nb_font)

For i = 0 To nb_font
	font(i) = LoadFont(#PB_Any, "Arial", i * 2 + 4)
Next

StartDrawing(ImageOutput(0))

y = 5
For i = 0 To nb_font
	DrawingFont(FontID(font(i)))
	DrawText(20, 5 + y, "Ceci est un TEST !", #White)
	
	y = y + 1 + TextHeight(" ")
Next

Dim image.a(w+1, h+1)
Dim image2.a(w+1, h+1)

For x = 1 To w
	For y = 1 To h
		c = Point(x, y)
		image(x, y) = (Red(c) + Green(c) + Blue(c)) / 3
	Next
Next

StopDrawing()


;}

REDRAW = #True
angle = 20
rayon = 3


;{ boucle principale

Repeat
	event = WaitWindowEvent()
	
	;{ event
	
	If event = #PB_Event_Gadget
		If EventGadget() = 0
			If EventType() = #PB_EventType_KeyDown
				Select GetGadgetAttribute(0, #PB_Canvas_Key)
					Case #PB_Shortcut_Escape
						event = #PB_Event_CloseWindow
						
					Case #PB_Shortcut_Up
						REDRAW = #True
						
						angle + 10
						If angle > 360 : angle - 360 : EndIf
						
					Case #PB_Shortcut_Down
						REDRAW = #True
						
						angle - 10
						If angle < 0 : angle + 360 : EndIf
						
					Case #PB_Shortcut_Left
						REDRAW = #True
						
						rayon + 1
						If rayon > 10 : rayon = 10 : EndIf
						
					Case #PB_Shortcut_Right
						REDRAW = #True
						
						rayon - 1
						If rayon < 1 : rayon = 1 : EndIf
						
				EndSelect
			EndIf
		EndIf
	EndIf
	
	;}
	
	;{ dessin
	
	If REDRAW
		StartDrawing(CanvasOutput(0))
		
		Box(0, 0, OutputWidth(), OutputHeight(), #Blue)
		
		time = ElapsedMilliseconds()
		CopyArray(image(), image2())
		
		GetEdgeGray(image2(), rayon)
		DrawRotatedArrayGray(image2(), 400, 0, 0, 0, angle * #PI / 180, #Red)
		time = ElapsedMilliseconds() - time
		
		DrawText(10, OutputHeight() - 20, Str(time) + " ms")
		DrawText(10, OutputHeight() - 40, "Up / Down pour faire varier l'angle (alpha = " + Str(angle) + "°)")
		DrawText(10, OutputHeight() - 60, "Left / Rigth pour faire varier le rayon (rayon = " + Str(rayon) + ")")
		
		
		StopDrawing()
		REDRAW = #False
	EndIf
	
	;}
	
Until event = #PB_Event_CloseWindow


;}


End
_________________________________________________
Mon site : CeriseCode (Attention Chantier perpétuel ;))
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

Re: Opération sur les Fonts

Message par nico »

Magnifique, merci pour le partage. :)
Avatar de l’utilisateur
Ar-S
Messages : 9476
Inscription : dim. 09/oct./2005 16:51
Contact :

Re: Opération sur les Fonts

Message par Ar-S »

Le résultat est super propre, même avec la rotation + modification d’épaisseur.
Bravo.
~~~~Règles du forum ~~~~
⋅.˳˳.⋅ॱ˙˙ॱ⋅.˳Ar-S ˳.⋅ॱ˙˙ॱ⋅.˳˳.⋅
W11x64 PB 6.x
Section HORS SUJET : ICI
LDV MULTIMEDIA : Dépannage informatique & mes Logiciels PB
UPLOAD D'IMAGES : Uploader des images de vos logiciels
Avatar de l’utilisateur
kernadec
Messages : 1594
Inscription : ven. 25/avr./2008 11:14

Re: Opération sur les Fonts

Message par kernadec »

bonjour Graph100
Merci pour le partage, vraiment top la classe, je suis impressionné!

Cordialement
Répondre