AH YES !!!!
C'est excellent, c'est exactement ce que l'on cherchait à faire, c'est juste fabuleux !!
Merci beaucoup kwandjeen ! Tu as super assuré !!
bravo ! Tu ne peux pas savoir comme je suis content, là
Nouveauté
Du coup J'ai ajouté d'autres petites bricoles, comme :
- le changement de taille aléatoire
- la diffusion aléatoire (en gros, le pinceau est dessiné en x+random(scatter)-random(scatter), et idem pour y

.
- le changement de brush : pour l'instant c'est avec la molette de la souris, mais ça ne va que dans un sens, car je ne voulais pas encore utiliser initmouse(), sinon, on perd le focus de la souris, mais je pense qu'on devra l'utiliser par la suite)
- on peut importer une image sur le canvas (dessin)
- on peut exporter notre dessin (en png, ou en jpg)
- j'ai ajouté 59 nouveaux brushes : amusez-vous à les tester (ce sont les mêmes brushes que mon logiciel animatoon)
Je vais tester d'autres ajouts bientôt

.
voici le code :
Code : Tout sélectionner
;{ Infos
;###################################################################
;#### kernadec juin 2011 Forum français ver 4.60 b3
;#### exemple canvas de dessin avec souris bouton Gauche relaché
;#### et bouton droit annule
;###################################################################
;
; Ajout : pinceau : blendman
;
; Aide : le soldat inconnu : fatroundbox() et fat box()
; Aide : Fred & pb team : exemple canvas gadget
; Super Aide excellente : kwandjeen, un immense merci !
;}
;{ Enumeration
Enumeration
#Window
#Image0
#Image1
#IMAGE_LoadSave
#Scroll
#canvas
#brush
#pbrush
EndEnumeration
Enumeration
#menu0
#menu1
#menu2
#menu3
#menu4
#menu5
#menu6
#menu7
#menu8
#menu9
#menu10
EndEnumeration
;}
If UseJPEGImageDecoder() = 0 Or UsePNGImageDecoder() = 0 Or UseJPEGImageEncoder() = 0 Or UsePNGImageEncoder()=0
MessageRequester("Erreur", "Erreur de chargement des decoder images")
End
EndIf
; If InitKeyboard() = 0
; MessageRequester("Erreur", "Erreur de chargement des sprites")
; End
; EndIf
LoadImage(#brush,"data\blendman\brush1.png")
;{ variables
; general
Global event.i, quit.b,clic_gauche.b, menu.a = 9,key.u, resize.b=1, brush_w, brush_h
; document
Global size_imgX.u=3000, Size_imgY.u=3000
; position souris, donc pinceau, etc..
Global x, y, DepartX, DepartY, rx, ry, finX, finY
; paramètres brush
Global brushId.u=1, transparence.a = 255, color.i, linesize.u=100, color_R.a, color_G.a, color_B.a
; aléatoire du brush
Global random_size.b, random_rotation.b, random_scatter.b, radiusX.u=5,radiusY.u=5, size.u=100, scatter.u=20
;}
;{ procedures
;{ procedure tools
Procedure FatBox(x, y, Width, Height, Fat, Color)
;le soldat inconu
For i = 1 To Fat
Box(x + i, y + i, Width - 2 * i, Height - 2 * i, Color)
Next
EndProcedure
Procedure FatRoundBox(x, y, Width, Height, RoundX, RoundY, Fat, Color)
For i = 1 To Fat
RoundBox(x + i, y + i, Width - 2 * i, Height - 2 * i, RoundX, RoundY, Color)
RoundBox(x, y + i, Width, Height - 2 * i, RoundX, RoundY, Color)
RoundBox(x + i, y, Width - 2 * i, Height, RoundX, RoundY, Color)
If i > 1
RoundBox(x + i - 1, y + i, Width - 2 * i + 2, Height - 2 * i, RoundX, RoundY, Color)
RoundBox(x + i, y + i - 1, Width - 2 * i, Height - 2 * i + 2, RoundX, RoundY, Color)
EndIf
Next
EndProcedure
Procedure ThickLineXY(X1.i, Y1.i, X2.i, Y2.i, Thickness.i, Color.i)
; Procedure épaisseur de : STARGATE forum Purebasic Allemand
Protected Length.i = Sqr((X2-X1)*(X2-X1)+(Y2-Y1)*(Y2-Y1))
Protected I, DeltaX.i, DeltaY.i
If Length = 0
Circle(X1, Y1, Thickness/2, Color)
Else
For I = 0 To Length
DeltaX = (X2-X1)*I/Length
DeltaY = (Y2-Y1)*I/Length
Circle(X1+DeltaX, Y1+DeltaY, Thickness/2, Color)
Next
EndIf
EndProcedure
Procedure elipse(x0,y0,x1,y1,r1,r2,a1,a2,Thickness,color)
For i=0 To 359
r3=(Sqr(Pow(x1,2)+Pow(y1,2)))
x2.i=x0+r3*Cos(Radian(i))
y2.i=y0+r3*Sin(Radian(i))
Circle(X2,Y2,Thickness/2,Color)
Next i
EndProcedure
Procedure paint_brush()
CopyImage(#brush,#pbrush) ; on copie le brush pour travailler sans modifier l'origine
If resize = 1
ResizeImage(#pbrush,linesize,linesize) ;on modifie la taille du brush
EndIf
brush_w = ImageWidth(#pbrush)
brush_h = ImageHeight(#pbrush)
StartDrawing(ImageOutput(#pbrush))
For y=0 To ImageHeight(#pbrush)-1
For x=0 To ImageWidth(#pbrush)-1
DrawingMode(#PB_2DDrawing_AlphaChannel)
alpha_point = Alpha(Point(x,y))-(255-transparence) ;on récupère l'alpha du brush (pixel par pixel) qu'on modifie par la valeur transparence
If alpha_point<0
alpha_point = 0
EndIf
DrawingMode(#PB_2DDrawing_AllChannels)
Plot(x,y,RGBA(color_R, color_G,color_B,alpha_point)) ;on redessine chaque point par la nouvelle couleur et l'alpha modifiée
Next x
Next y
StopDrawing()
EndProcedure
;}
Procedure Event_painting()
key = GetGadgetAttribute(#canvas,#PB_Canvas_Keyboard)
X = GetGadgetAttribute(#canvas, #PB_Canvas_MouseX)
Y = GetGadgetAttribute(#canvas, #PB_Canvas_MouseY)
StartDrawing(CanvasOutput(#canvas))
;{ dessin (outils & pinceau)
If Clic_Gauche=#True And menu <>9
;{ EventType() = #PB_EventType_MouseMove
If EventType() = #PB_EventType_MouseMove
DrawImage(ImageID(#Image0), 0, 0)
If menu<>10
DrawingMode(#PB_2DDrawing_AlphaBlend| #PB_2DDrawing_Transparent) ; transparence avec couleur RGBA
Else
DrawingMode(#PB_2DDrawing_AlphaBlend|#PB_2DDrawing_Outlined | #PB_2DDrawing_Transparent)
EndIf
; calcul des distances pixels entre DepartX,DepartY du debut et X,Y actuel = taille de l'élipse
If x > DepartX:rx = x - DepartX:Else:rx = DepartX - x:EndIf
If y > DepartY:ry = y - DepartY:Else:ry = DepartY - y:EndIf
If menu=1
LineXY(DepartX, DepartY, x, y, color)
FinX=x:FinY=y
EndIf
If menu=2
ThickLineXY(DepartX, DepartY, x, y, linesize, Color)
FinX=x:FinY=y
EndIf
If menu=3
Ellipse(DepartX, DepartY, rx, ry, color)
EndIf
If menu=4
elipse(DepartX,DepartY,x-DepartX,y-DepartY,r1,r2,a1,a2,linesize,color)
EndIf
If menu=5
Box(DepartX, DepartY,x-DepartX,y-DepartY,color)
EndIf
If menu = 10
FatBox(DepartX, DepartY,x-DepartX,y-DepartY,linesize,color)
EndIf
If menu = 11
FatRoundBox(DepartX, DepartY,x-DepartX,y-DepartY,10,10,linesize,color)
EndIf
EndIf
;}
ElseIf menu =9 And clic_gauche = #True
DrawingMode(#PB_2DDrawing_AlphaBlend)
;Ellipse(x+random_x,y+random_y,linesize-random_size*u,linesize-random_size*u,color)
;RotateImage(ImageID(#pbrush),60)
If random_size = 1
size = 1+Random(linesize-1)
ElseIf random_size = 0
size = linesize
EndIf
If random_scatter =1
DrawImage(ImageID(#pbrush),x-(ImageWidth(#pbrush)/2)+Random(scatter)-Random(scatter),y-(ImageHeight(#pbrush)/2)+Random(scatter)-Random(scatter),size,size)
ElseIf random_scatter=0
DrawImage(ImageID(#pbrush),x-(ImageWidth(#pbrush)/2),y-(ImageHeight(#pbrush)/2),size,size)
EndIf
EndIf
;}
;{ autre
If menu = 9
If EventType() = #PB_EventType_LeftButtonDown
If Clic_Gauche=#True
Clic_Gauche=#False
color= RGBA(color_R, color_G,color_B,transparence) ; couleur aléatoire
; CopyImage(#Image0,#Image1)
Else
Clic_Gauche=#True
EndIf
ElseIf EventType() = #PB_EventType_LeftButtonUp
If Clic_Gauche=#True
Clic_Gauche=#False
color= RGBA(color_R, color_G,color_B,transparence) ; couleur aléatoire
CopyImage(#Image0,#Image1)
Else
Clic_Gauche=#True
EndIf
EndIf
EndIf
;}
If EventType() = #PB_EventType_RightButtonDown And Clic_Gauche=#True And menu <>9
Clic_Gauche=#False ; annule fin du dessin en cours
DrawImage(ImageID(#Image1),0,0) ; restore le dessin precedent
FinX=0:FinY=0 ; remise à zero pour test fin ligne
EndIf
StopDrawing()
;{ eventType()
Select EventType()
Case #PB_EventType_LeftButtonDown
If menu <>9
If StartDrawing(ImageOutput(#Image0))
DrawImage(GetGadgetAttribute(#canvas,#PB_Canvas_Image),0,0) ;fixe le dessin
StopDrawing()
EndIf
If Clic_Gauche=#False ; valide la fin du dessin avec le click gauche = 0
Clic_Gauche=#True ; debut du dessin avec le click gauche = 1
color= RGBA(color_R, color_G,color_B,transparence) ; couleur aléatoire
CopyImage(#Image0,#Image1) ; copie Image pour eventuelle annulation
Else
Clic_Gauche=#False ; valide la fin du dessin avec le click gauche = 0
EndIf
DepartX = X ; coordonnée DepartX Clic_Gauche
DepartY = Y ; coordonnée DepartY Clic_Gauche
If menu=1 Or menu=2
If (FinX<>0 And FinY<>0)
Clic_Gauche=#True ; reactive le clic_Gauche pour ligne suivante
CopyImage(#Image0,#Image1) ; copie Image pour eventuelle annulation
DepartX = FinX ; transfert dernier clic_Gauche FinX vers DepartX suivant mode line chainée
DepartY = FinY ; transfert dernier clic_Gauche FinY vers DepartY suivant
EndIf
EndIf
ElseIf menu =9
If StartDrawing(ImageOutput(#Image0))
DrawImage(GetGadgetAttribute(#canvas,#PB_Canvas_Image),0,0) ;fixe le dessin
StopDrawing()
EndIf
EndIf
Case #PB_EventType_MouseWheel
If brushid <59
brushId + 1
Else
brushId = 1
EndIf
Debug brushId
LoadImage(#brush,"data\blendman\brush"+Str(brushId)+".png")
resize = 1
paint_brush()
EndSelect
;}
Select event
;{ #PB_Event_Menu
Case #PB_Event_Menu
Select EventMenu()
Case #menu1: menu=1
Case #menu2: menu=2
Case #menu3: menu=3
Case #menu4: menu=4
Case #menu5: menu=5
Case #menu6: transparence = Val(InputRequester("Transparence","transparence du pinceau", Str(transparence)))
If transparence <0 : transparence = 0 : color= RGBA(color_R, color_G,color_B,transparence)
ElseIf transparence>255 : transparence = 255 : color= RGBA(color_R, color_G,color_B,transparence)
EndIf
resize = 0
paint_brush()
Case #menu7: couleur = ColorRequester(couleur)
color_R=Red(couleur)
color_G=Green(couleur)
color_B=Blue(couleur)
color= RGBA(color_R, color_G,color_B,transparence)
resize = 0
paint_brush()
Case #menu8: linesize = Val(InputRequester("Taille","Epaisseur de la ligne", Str(linesize)))
color= RGBA(color_R, color_G,color_B,transparence)
resize = 1
paint_brush()
resize = 0
Case #menu9 : menu = 9
color= RGBA(color_R, color_G,color_B,transparence)
resize = 0
Case 10 : menu = 10
Case 11 : menu = 11
Case 20 ; nouveau
Case 21 ; Ouvrir
Case 22 ; enregistrer
Case 23 ; quitter
End
Case 24 ; importer une image
File$ = OpenFileRequester("Load Image...", "", "JPEG Images|*.jpg|PNG IMages|*.png|All Files|*.*", 0)
If File$
If LoadImage(#IMAGE_LoadSave, File$)
If StartDrawing(CanvasOutput(#Canvas))
Box(0, 0, 380, 380, $FFFFFF)
DrawImage(ImageID(#IMAGE_LoadSave), 0, 0)
StopDrawing()
EndIf
FreeImage(#IMAGE_LoadSave)
Else
MessageRequester("CanvasGadget", "Impossible de charger une image: " + File$)
EndIf
EndIf
Case 25 ; exporter l'image
File$ = SaveFileRequester("Save Image...", File$, "JPEG Images|*.jpg", 0)
If File$ And (FileSize(File$) = -1 Or MessageRequester("CanvasGadget", "Ecraser le fichier? " + File$, #PB_MessageRequester_YesNo) = #PB_MessageRequester_Yes)
If CreateImage(#IMAGE_LoadSave, size_imgX,size_imgX, 24) And StartDrawing(ImageOutput(#IMAGE_LoadSave))
DrawImage(GetGadgetAttribute(#Canvas, #PB_Canvas_Image), 0, 0)
StopDrawing()
If SaveImage(#IMAGE_LoadSave, File$, #PB_ImagePlugin_JPEG,9,24) = 0
MessageRequester("CanvasGadget", "Sauvegarde impossible: " + File$)
EndIf
FreeImage(#IMAGE_LoadSave)
EndIf
EndIf
Case 26
File$ = SaveFileRequester("Save Image...", File$, "PNG Images|*.png", 0)
If File$ And (FileSize(File$) = -1 Or MessageRequester("CanvasGadget", "Ecraser le fichier? " + File$, #PB_MessageRequester_YesNo) = #PB_MessageRequester_Yes)
If CreateImage(#IMAGE_LoadSave, size_imgX,size_imgX, 32) And StartDrawing(ImageOutput(#IMAGE_LoadSave))
DrawImage(GetGadgetAttribute(#Canvas, #PB_Canvas_Image), 0, 0)
StopDrawing()
If SaveImage(#IMAGE_LoadSave, File$, #PB_ImagePlugin_PNG,32) = 0
MessageRequester("CanvasGadget", "Sauvegarde impossible: " + File$)
EndIf
FreeImage(#IMAGE_LoadSave)
EndIf
EndIf
Case 30 ; effacer le canvas
If StartDrawing(CanvasOutput(#Canvas))
Box(0, 0, size_imgX,size_imgy, $FFFFFF)
StopDrawing()
EndIf
Case 40
MessageRequester("A propos", "Canvas gadget est un logiciel créé par Kernadec et Blendman."+Chr(10)+"Ce logiciel est développé en purebasic"+Chr(10)+Chr(10)+"Canvas Gadget est libre et gratuit."+Chr(10)+Chr(10)+"Créé en Juillet 2011"+Chr(10)+"Version : 0.0.2")
Case 50 ; afficher les calques
Case 100 ; taille aléatoire
random_size = 1-random_size
SetMenuItemState(0,100,random_size)
Case 101 ; random_rotation
random_rotation =1-random_rotation
SetMenuItemState(0,101,random_rotation)
Case 102 ; random scatter (diffusion aléatoire
random_scatter =1-random_scatter
SetMenuItemState(0,102,random_scatter)
Case 103 ; scatter (diffusion)
scatter = Val(InputRequester("Diffusion","Valeur de transparence du pinceau", Str(scatter)))
If scatter <0 : scatter = 0
ElseIf scatter>500 : scatter = 500
EndIf
EndSelect
;}
;{ #PB_Event_SizeWindow
Case #PB_Event_SizeWindow ; redimensione le scroll avec la fenetre
ResizeGadget(#Scroll,#PB_Ignore,#PB_Ignore,WindowWidth(#Window),WindowHeight(#Window)-20) ; -20 = scroll horizontal et menu
SetGadgetColor(#Scroll,#PB_Gadget_BackColor,#White)
;}
;{ #PB_Event_CloseWindow
Case #PB_Event_CloseWindow
quit=1
;}
EndSelect
EndProcedure
Procedure Event_keyboard()
;ExamineKeyboard()
EndProcedure
Procedure OpenWin()
CreateImage(#Image0, size_imgX, size_imgY, 32|#PB_Image_Transparent)
CreateImage(#Image1, size_imgX, size_imgY, 32|#PB_Image_Transparent)
size = linesize
If OpenWindow(#Window, 0, 0,600,600, "CanvasGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered| #PB_Window_MinimizeGadget | #PB_Window_SizeGadget|#PB_Window_MaximizeGadget|#PB_Window_Maximize)
ScrollAreaGadget(#Scroll, 0, 0, 600,600, size_imgX, size_imgY, 30)
CanvasGadget(#canvas,0,0,size_imgX, size_imgY, #PB_Canvas_ClipMouse| #PB_Canvas_Keyboard)
SetWindowColor(#Window,RGB(125,125,125))
SetGadgetColor(#Scroll,#PB_Gadget_BackColor,#Gray)
SetGadgetAttribute(#Scroll,#PB_ScrollArea_X,200)
SetGadgetAttribute(#Scroll,#PB_ScrollArea_Y,200)
If CreateMenu(#menu0, WindowID(0))
; menu Fichier
MenuTitle("Fichier")
MenuItem(20,"Nouveau")
MenuItem(21,"ouvrir")
MenuItem(24,"Importer une image sur le calque")
MenuItem(25,"Exporter L'image en jpg")
MenuItem(26,"Exporter L'image en png")
MenuItem(22,"Enregistrer")
MenuItem(23,"Quitter")
; menu Edition
MenuTitle("Edition")
MenuItem(30,"Effacer")
; menu image
MenuTitle("Images")
; Menu outils
MenuTitle("Outils")
MenuItem(#menu1, "Ligne")
MenuItem(#menu2, "Ligne Epaisse")
MenuItem(#menu3, "Cercle")
MenuItem(#menu4, "Cercle vide")
MenuItem(#menu5, "Box")
MenuItem(10,"box vide")
MenuItem(11,"Roundbox")
MenuItem(#menu9, "Pinceau")
; Menu paramètres
MenuTitle("Paramètres")
MenuItem(100,"Taille Aléatoire")
SetMenuItemState(0,100,random_size)
MenuItem(101,"Rotation Aléatoire")
SetMenuItemState(0,101,random_rotation)
MenuItem(102,"Diffusion Aléatoire")
SetMenuItemState(0,101,random_scatter)
MenuItem(103,"Diffusion")
MenuItem(#menu6, "Transparence")
MenuItem(#menu7, "Couleur")
MenuItem(#menu8, "Taille ligne")
; menu fenêtre
MenuTitle("Affichage")
MenuItem(50,"Calques")
; Menu Aides
MenuTitle("Aides")
MenuItem(40,"A propos")
MenuItem(41,"Aide")
EndIf
color= RGBA(color_R, color_G,color_B,transparence)
Else
MessageRequester("Erreur", "impossible d'ouvrir une fenêtre")
End
EndIf
EndProcedure
;}
OpenWin()
paint_brush()
Repeat
event=WaitWindowEvent()
Event_keyboard()
Event_painting()
Until quit
Et les brushs, vous devez les placer à la racine de votre exe, dans le même répertoire que l'exe que vous créez :
http://blendman.free.fr/dev/pb/soft2D/data.zip
Il faudrait un nom pour ce petit logiciel, avez-vous une idée ?
Sinon quelques propositions :
- canvas gadget
- photopaint
- brush Ink
- Pure Canvas
- Pure Painting
- DrawPure
- PureBrush
- animatoon ( c'est le nom de mon autre soft 2D, car il va être assez proche en fait, avec pas mal d'outils en plus

).
Questions
Par contre, j'ai essayé de faire une rotation aléatoire, mais je n'ai pas encore réussi, si vous avez une idée, ce serait géniale

Là, on a les bases d'un excellent logiciel 2D de painting, si on ajoute la rotation, aléatoire, on va pouvoir concevoir des outils fabuleux, comme :
- craie
- fusain
- crayon, crayon gris, conté
- encre
- aquarelle
- ajout d'eau, diffusion de l'eau
Prochains ajouts / outils
1. Nouveaux paramètres de la brosse :
Rotation
Ce serait formidable si on pouvait ajouter la rotation aux brushs, genre :
rotateImage(#pbrush, angle)
Pour la rotation, j'ai trouvé divers codes
Le 1er : je ne trouve pas cette astuce très performante pour nous, car on aurait des rotations aléatoires (environ 20 par secondes), donc je vois mal enregistrer sur le disque à chaque fois l'image

:
Code : Tout sélectionner
; German forum: http://www.purebasic.fr/german/archive/viewtopic.php?t=1596&highlight=
; Author: Andreas (updated for PB4.00 by blbltheworm + Andre)
; Date: 05. July 2003
; OS: Windows
; Demo: No
#LoadImage = #True ; set to #False if you want to use a on-the-fly created image
#Window_0 = 0
#Gadget_0 = 0
#Gadget_1 = 1
Procedure Rotate(Image$)
Image1Dc = CreateCompatibleDC_(0)
Image1 = LoadImage_(0, Image$, 0, 0, 0, $2050)
OldObject = SelectObject_(Image1Dc, Image1)
GetObject_(Image1, SizeOf(BITMAP), bmp.BITMAP)
Image2Dc = CreateCompatibleDC_(0)
Image2 = CreateCompatibleBitmap_(Image1Dc, bmp\bmHeight, bmp\bmWidth)
SelectObject_(Image2Dc, Image2)
ia = bmp\bmHeight
While ia > 0
i = 0
While i < bmp\bmWidth
BitBlt_(Image2Dc, bmp\bmHeight-ia, i, 1, 1, Image1Dc, i, ia, #SRCCOPY)
i = i + 1
Wend
ia = ia - 1
Wend
CreateImage(2, bmp\bmHeight, bmp\bmWidth)
Windc = StartDrawing(ImageOutput(2))
StretchBlt_(Windc, 0, 0, bmp\bmHeight, bmp\bmWidth, Image2Dc, 0, 0, bmp\bmHeight, bmp\bmWidth, #SRCCOPY)
StopDrawing()
ReleaseDC_(0, Image1Dc)
DeleteObject_(Image1)
ReleaseDC_(0, Image2Dc)
DeleteObject_(Image2)
EndProcedure
Procedure Open_Window_0()
If OpenWindow(#Window_0, 381, 90, 1024, 768, "Image Rotation...", #PB_Window_SystemMenu | #PB_Window_TitleBar )
If CreateGadgetList(WindowID(#Window_0))
ImageGadget(#Gadget_0, 5, 5, 300, 200, ImageID(0))
ImageGadget(#Gadget_1, 40, 270, 0, 0, 0)
EndIf
EndIf
EndProcedure
CompilerIf #LoadImage = #True
UsePNGImageDecoder()
UseJPEGImageDecoder()
LoadImage(0, "brush_paint.jpg")
CompilerElse
font = LoadFont(0, "Arial", 40)
CreateImage(0, 300, 200)
StartDrawing(ImageOutput(0))
DrawingFont(font)
DrawText(100, 100, "Test")
StopDrawing()
CompilerEndIf
Open_Window_0()
SaveImage(0, "~~temp.bmp", #PB_ImagePlugin_BMP)
rotate("~~temp.bmp")
DeleteFile("~~temp.bmp")
SetGadgetState(#Gadget_1, ImageID(2))
Repeat
Until WaitWindowEvent()=#PB_Event_CloseWindow
; IDE Options = PureBasic v4.02 (Windows - x86)
; Folding = -
; EnableXP
Le 2 : celui pourrait être intéressant, à tester.
Si vous avez une autre idée, n'hésitez pas à poster.
Code : Tout sélectionner
; German forum: http://www.purebasic.fr/german/viewtopic.php?t=4512&highlight=
; Author: PureLust (updated for PB 4.00 by Andre)
; Date: 03. October 2005
; OS: Windows
; Demo: Yes
Define.w OrigBreite, OrigHoehe, OrigXDrehpunkt, OrigYDrehpunkt, ZielBreite, ZielHoehe, Rand
; Standardvariablen definieren
#GFX_Mittelwertfilter = 1
OrigBreite=200
OrigHoehe=200
OrigXDrehpunkt=45
OrigYDrehpunkt=45
ZielBreite=OrigBreite
ZielHoehe=OrigHoehe
Rand=20
Filterung.b=#GFX_Mittelwertfilter
Filterung.b=0
Dim OrigPoint(OrigBreite+1, OrigHoehe+1)
If OpenWindow(0, 10, 10, OrigBreite*2+Rand*3, OrigHoehe+Rand*2, " 2D Image-Rotation <ESC>-Ende <Space>-Pause <F>-Filter", 0)
If CreateImage(1, OrigBreite, OrigHoehe)
; original Ausgangsbild erzeugen
If StartDrawing(ImageOutput(1))
Box(1, 1, OrigBreite-2, OrigHoehe-2, RGB(255, 255, 255))
Box(20, 30, OrigBreite-40, 30, RGB(20, 200, 200))
;Circle(OrigXDrehpunkt, OrigYDrehpunkt, 4, RGB(0, 0, 255))
;Circle(OrigXDrehpunkt, OrigYDrehpunkt, 2, RGB(255, 255, 255))
Circle(40, OrigHoehe-41, 30, RGB(200, 33, 33))
; Daten des Originalbildes in einem Array zwischenspeichern
For x.w = 1 To OrigBreite
For y.w = 1 To OrigHoehe
OrigPoint(x, y)=Point(x-1, y-1)
Next y
Next x
StopDrawing()
EndIf
If StartDrawing(WindowOutput(0))
Hintergrundfarbe = Point(1, 1)
; Im Bildpuffer einen Rahmen in Hintergrundfarbe um das Bild legen (für Filter)
For x=0 To OrigBreite : OrigPoint(x, 0)=Hintergrundfarbe : OrigPoint(x, OrigHoehe+1)=Hintergrundfarbe : Next x
For Y=0 To OrigHoehe : OrigPoint(0, y)=Hintergrundfarbe : OrigPoint(OrigBreite+1, y)=Hintergrundfarbe : Next y
; Originalbild auf Fenster ausgeben
OrigImageID=ImageID(1)
DrawImage(OrigImageID, Rand, Rand)
StopDrawing()
EndIf
If CreateImage(2, ZielBreite, ZielHoehe)
Repeat
For w = 0 To 359
Winkel.f = 3.141/180*w
; mehrfach benutzte Berechnungen puffern
SinWinkel.f = Sin(Winkel)
CosWinkel.f = Cos(Winkel)
ZielImageID=ImageID(2)
If StartDrawing(ImageOutput(2))
; Zielimage löschen
Box(0, 0, ZielBreite, ZielHoehe, Hintergrundfarbe)
StartTimer = ElapsedMilliseconds()
For x.w = 1 To OrigBreite
; mehrfach benutzte Berechnungen puffern
xSinWinkel.f = (x-OrigXDrehpunkt)*SinWinkel
xCosWinkel.f = (x-OrigXDrehpunkt)*CosWinkel
For y.w = 1 To OrigHoehe
zx.f=(xCosWinkel-(y-OrigYDrehpunkt)*SinWinkel)+OrigXDrehpunkt
zy.f=(xSinWinkel+(y-OrigYDrehpunkt)*CosWinkel)+OrigYDrehpunkt
Select Filterung
Case #GFX_Mittelwertfilter
; Berechnung mit Filter
zxi = Int(zx+0.5)
zyi = Int(zy+0.5)
If zx>0 And zx<ZielBreite+1 And zy>0 And zy<ZielHoehe+1
PixelFarbe1 = OrigPoint(zxi, zyi)
If zx<zxi
PixelFarbe2 = OrigPoint(zxi-1, zyi)
Else
PixelFarbe2 = OrigPoint(zxi+1, zyi)
EndIf
Gewichtung2.f=Abs(zx-zxi)
If zy>zyi
PixelFarbe3 = OrigPoint(zxi, zyi+1)
Else
PixelFarbe3 = OrigPoint(zxi, zyi-1)
EndIf
Gewichtung3.f=Abs(zy-zyi)
Gewichtung1.f=1-Gewichtung2-Gewichtung3
; Pixelgewichtung berechnen
PixelRed=Red(PixelFarbe1)*Gewichtung1+Red(PixelFarbe2)*Gewichtung2+Red(PixelFarbe3)*Gewichtung3
PixelGreen=Green(PixelFarbe1)*Gewichtung1+Green(PixelFarbe2)*Gewichtung2+Green(PixelFarbe3)*Gewichtung3
PixelBlue=Blue(PixelFarbe1)*Gewichtung1+Blue(PixelFarbe2)*Gewichtung2+Blue(PixelFarbe3)*Gewichtung3
Plot(x-1, y-1, RGB(PixelRed, PixelGreen, PixelBlue))
EndIf
Default
; Berechnung ohne Filter
If zx>=1 And zx<ZielBreite+1 And zy>=1 And zy<ZielHoehe+1
Plot(x-1, y-1, OrigPoint(Int(zx), Int(zy)))
EndIf
EndSelect
Next y
Next x
StopDrawing()
SetWindowTitle(0, " 2D Image-Rotation <ESC>-Ende <Space>-Pause <F>-Filter FPS: "+Str(1000/(ElapsedMilliseconds()-StartTimer+1)))
EndIf
If StartDrawing(WindowOutput(0))
; gedrehtes Image auf Fenster ausgeben
DrawImage(ZielImageID, rand*2+OrigBreite, Rand)
StopDrawing()
EndIf
Event=WindowEvent()
If Event = #WM_KEYDOWN
If EventwParam() = #VK_SPACE
Repeat
Event=WaitWindowEvent()
Until Event = #WM_KEYDOWN
ElseIf EventwParam() = #VK_F
Filterung = #GFX_Mittelwertfilter-Filterung
ElseIf EventwParam() = #VK_ESCAPE
Break 2
EndIf
EndIf
Next w
ForEver
EndIf
EndIf
EndIf
End
; IDE Options = PureBasic v4.02 (Windows - x86)
; Folding = -
; EnableXP
; DisableDebugger
Une autre chose fabuleuse serait le fait de "lier" chaque point dessiner par les motifs de la brosse :
donc, au lieu d'avoir le trait du haut, on aurait le trait du bas :
J'ai trouvé ce code sur le forum Anglais, ça pourrait servir je pense :
Code : Tout sélectionner
Global lpPrevFunc
Procedure StaticProc(hWnd,uMsg,wParam,lParam)
Static MTX,MTY
Select uMsg
Case #WM_LBUTTONDOWN
MX = lParam & $FFFF : MY = lParam >> 16
MTX = MX : MTY = MY
StartDrawing(ImageOutput(0))
Plot(MX,MY,#White)
StopDrawing()
result = CallWindowProc_(lpPrevFunc,hWnd,uMsg,wParam,lParam)
SetCapture_(hWnd)
Case #WM_MOUSEMOVE
If wParam & #MK_LBUTTON
GetCursorPos_(cpt.POINT)
ScreenToClient_(hWnd,cpt)
MX = cpt\x : MY = cpt\y
StartDrawing(ImageOutput(0))
LineXY(MTX,MTY,MX,MY,#White)
StopDrawing()
MTX = MX : MTY = MY
SetGadgetState(0,ImageID(0))
Else
result = CallWindowProc_(lpPrevFunc,hWnd,uMsg,wParam,lParam)
EndIf
Case #WM_LBUTTONUP
ReleaseCapture_()
result = CallWindowProc_(lpPrevFunc,hWnd,uMsg,wParam,lParam)
Default
result = CallWindowProc_(lpPrevFunc,hWnd,uMsg,wParam,lParam)
EndSelect
ProcedureReturn result
EndProcedure
CreateImage(0,300,220)
StartDrawing(ImageOutput(0))
Box(0,0,310,230,#Gray)
StopDrawing()
OpenWindow(0,0,0,320,240,"PurePaint",#PB_Window_SystemMenu | #PB_Window_ScreenCentered)
CreateGadgetList(WindowID(0))
ImageGadget(0,10,10,0,0,ImageID(0),0)
lpPrevFunc = SetWindowLong_(GadgetID(0),#GWL_WNDPROC,@StaticProc())
While WaitWindowEvent() ! #PB_Event_CloseWindow : Wend
2. Calques
Il serait aussi excellent d'ajouter par la suite :
- des calques (avec canal alpha et transparence)
- mode de fusion des calques.
G-rom me disait que l'on pouvait utiliser plusieurs image pour cela, mais je n'ai pas encore tester ça.
Pour les modes de Fusion, j'ai trouvé un ou 2 exemples, mais ils ne marchent pas hélas (trop anciens peut être). Je peux les poster si besoin.
3. mode aquarelle
L'idée serait de prendre la couleur d'un pixel (position de la souris) est de peindre avec.
avec un point(), je pense que ça devrait être faisable.
Si on pouvait d'ailleurs ensuite prendre la valeur de transparence aussi, ce serait excellent

.
j'ai déjà une petite idée de la façon de faire, mais si vous avez des idées, n'hésitez pas.
4. Interface
Je me disais qu'un zoom sur le canvas serait aussi un truc très intéressant, si vous avez une technique, on prend

.
D'ailleurs, n'hésitez surtout pas si vous voulez participer à ce projet
