Pure Reductor

Programmation d'applications complexes
Avatar de l’utilisateur
Zorro
Messages : 2185
Inscription : mar. 31/mai/2016 9:06

Pure Reductor

Message par Zorro »

Pure Reductor

n'est pas a proprement parlé fait pour reduire la taille des images

mais plutot un prg qui permet de reduire le nombre couleurs utilisé pour dessiner une image
par la suite un algo de compression pour etre mis en place pour profiter du nombre de couleurs reduite
et reduire la taille de l'image !

utilisation : (il y a plusieurs mode d'utilisations )

mode normal :
vous chargez une image , elle va se dessiner dans l'interface

[Nbr de couleurs] indique le nombre de couleur que vous voulez utiliser pour redessiner l'image
a noter que vous pouvez faire plusieurs essai, sans avoir a recharger l'image d'origine,le prg repart toujours de l'image d'origine meme si pas affichée
un appuis sur [Run] , ça bosse (indication en haut a gauche de la fenetre)

ça va afficher le resultat ....

le curseur vertical a gauche permet de regler la tolerance , plus il y a de tolerance, plus vous permettez au prg de prendre la couleur qu'il veux pour dessiner !
diminuer la tolerance, oblige le prg a utiliser un crayon de la palette le plus proche possible de la couleur a dessiner ....

faites des tests :)

Mode Pick :

dans ce mode, vous chargez une image
ensuite en activant le bouton [pick] , vous choisissez des pixels de couleur pour creer la palette de crayons pour le prg
chaque click = un crayon de plus (le compteur se met a jour dans l'interface )

ensuite vous reglez votre tolerance (ou pas) , et lancez le dessin avec [Run] !


la case a cocher Floyd sert a tramer en utilisant l'algo Floyd
la case Flou permet d'ajouter un leger flou sur l'image final



voici le code :

Code : Tout sélectionner


;***********************************************
;Titre  :*Pure_reductor_interface
;Auteur  : Dobro
;Date  :17/03/2016
;Heure  :18:01:29
;Version Purebasic : PureBasic 5.60 (Windows - x86)
;Version de l'editeur :EPB V2.64
; Libairies necessaire : Aucune 
;***********************************************



;{- Enumerations / DataSections
;{ Windows
Enumeration
		#Win
EndEnumeration
;}
;{ Gadgets
Enumeration
		#Button_Load
		#CheckBox_Floyd
		#CheckBox_Flou
		#TrackBar_tolerance
		#Text_info
		#Text_info2
		#Text_tol_val
		#Text_tolerance
		#Text_Titre
		#Container_8
		#Button_Run
		#String_nb_couleur
		#Text_color
		#Button_Save
		#zone_acenseur
		#image_palette
		#Button_pick
		#Image_ori
EndEnumeration

;}
;{ Fonts
Enumeration
		#Font_Text_Titre
EndEnumeration
;}
Define.l Event
InitMouse()
UseJPEGImageDecoder():UsePNGImageDecoder():UseTGAImageDecoder():UseTIFFImageDecoder()
UseJPEGImageEncoder()
Resultat = InitSprite()
Declare distance_couleur(couleur1,couleur2)
Declare  make_palette(nb_image,nbr_couleur.i,palette )
Declare  Dessin(nb_image,nbr_couleur,tolerance,Floyd,flou)
Declare  mise_en_tab_ori(nb_image,Largeur_image,Hauteur_image)
Declare  mise_en_tab(nb_image,largeur_image,hauteur_image)
Declare  flou(nb_image,imagex,imagey, niveau)
Declare  doomohundro(himg) ; floyd
Declare.i truncf0255 (a.f)
Declare  rgbtolum(c.l)  ;get luminosity (the min and max rgb levels / 2)
Enumeration
		#Image
		#image_resultat
		#Fenetre
		#file
EndEnumeration
Global NewList palette()
Global NewList des()
Global Flag_pick=-1,compteur,vertical,pas,compteur_coul,nbr_couleur,Flag_pick_pick

;}
Procedure OpenWindow_Win()
		If OpenWindow(#Win, 180, 5, 1096, 672, "Pure_reductor By Dobro", #PB_Window_SystemMenu|#PB_Window_SizeGadget|#PB_Window_MinimizeGadget|#PB_Window_TitleBar)
				;If CreateGadgetList(WindowID(#Win))
				ButtonGadget(#Button_Load, 15, 50, 90, 35, "Load Img")
				CheckBoxGadget(#CheckBox_Floyd, 15, 135, 105, 25, "Floyd Tramage")
				CheckBoxGadget(#CheckBox_Flou, 15, 160, 105, 25, "Flou")
				TrackBarGadget(#TrackBar_tolerance, 10, 235, 45, 310, 0,442, #PB_TrackBar_Ticks|#PB_TrackBar_Vertical)
				TextGadget(#Text_tolerance, 10, 210, 75, 25, "Tolerance")
				TextGadget(#Text_tol_val,90, 210, 40, 30,  "0")
				tolerance=0 ; Tolerance par defaut !
				SetGadgetState(#TrackBar_tolerance,tolerance) 
				SetgadgetText (#Text_tol_val,str(tolerance))
				SetgadgetText (#Text_tol_val,str(tolerance))
				TextGadget(#Text_Titre, 430, 15, 195, 40, "Pure_reductor")
				TextGadget(#Text_info, 20, 15, 100, 25, "Info")
				TextGadget(#Text_info2, 150,5, 195,40, "Info2")
				ButtonGadget(#Button_Run, 10, 545, 90, 35, "Run")
				StringGadget(#String_nb_couleur, 85, 90, 35, 20, "256")
				TextGadget(#Text_color, 15, 90, 70, 20, "Nbr Couleurs")
				ButtonGadget(#Button_Save, 10, 595, 90, 35, "Save Img")
				ButtonGadget(#Button_pick, 55, 240, 50, 20, "Pick",#PB_Button_Toggle )
				
				ScrollAreaGadget(#zone_acenseur,130, 55,  940, 595,0, 0, 30) 
				CanvasGadget(#image_palette, 0,55, 8*16, 8*256)
				ContainerGadget(#Container_8, 130, 55, 940, 595,#PB_Container_Double)
				OpenWindowedScreen(gadgetID(#Container_8),0, 0, 940, 595, 0, 0, 0 ) ; on met un ecrant dedans
				CloseGadgetList()
				; Gadget Fonts
				SetGadgetFont(#Text_Titre, LoadFont(#Font_Text_Titre, "Microsoft Sans Serif", 22, #PB_Font_HighQuality))
				;EndIf
		EndIf
EndProcedure
OpenWindow_Win()
;{- Event loop
Repeat
		Event = WaitWindowEvent(12)
		Select Event
				; ///////////////////
				Case #PB_Event_Gadget
				Select EventGadget()
						Case #Button_Load
						Flag_pick_pick=0 :vertical=0:compteur=0
						if FileSize("chemin.inf")<>-1
								if Openfile(#file,"chemin.inf")
										chemin$=ReadString(#file)
								CloseFile(#file)
								NomFichier$=OpenFileRequester("Charge une image", chemin$+"*.*", "", 0)
						Endif
						chemin$=GetPathPart(NomFichier$)
						Openfile(#file,"chemin.inf")
								WriteStringN(#file,chemin$)
						CloseFile(#file)
				Else
						NomFichier$ = OpenFileRequester("Charge une image", "*.*", "", 0) ; on choisi un ficher
						chemin$=GetPathPart(NomFichier$)
						Openfile(#file,"chemin.inf")
								WriteStringN(#file,chemin$)
						CloseFile(#file)
				Endif
				If NomFichier$<>""
						Resultat = LoadImage(#Image, NomFichier$ ) ; on charge une image
						global format$=GetExtensionPart(NomFichier$)
				EndIf
				if IsImage(#image)
						Global largeur_image=ImageWidth(#Image)
						Global Hauteur_image=ImageHeight(#Image)
						if largeur_image>Hauteur_image : ResizeImage(#image,1024,768):endif
						if largeur_image<Hauteur_image : ResizeImage(#image,768,1024):endif
						Global largeur_image=ImageWidth(#Image)
						Global Hauteur_image=ImageHeight(#Image)
						CloseScreen()
						OpenWindowedScreen(gadgetID(#Container_8),0, 0, largeur_image,Hauteur_image, 0, 0, 0 ) ; on met un ecran dedans
						CopyImage(#Image,#Image_ori)
						StartDrawing(ScreenOutput()) ;
								DrawImage(ImageID(#Image), 0, 0)
						StopDrawing()
						
						ResizeGadget(#container_8, #PB_Ignore, #PB_Ignore,Largeur_image, Hauteur_image)
						SetGadgetAttribute(#zone_acenseur, #PB_ScrollArea_InnerWidth  , Largeur_image+(Largeur_image/2))
						SetGadgetAttribute(#zone_acenseur, #PB_ScrollArea_InnerHeight  ,Hauteur_image+(Hauteur_image/2))
				Else
						MessageRequester("erreur", "l'image n'a pas pu etre chargée")
						End
				Endif
				GLobal Dim TAB_ori(Largeur_image,Hauteur_image) ; le Tableau
				GLobal Dim TAB(Largeur_image,Hauteur_image) ; le Tableau
				StartDrawing(ImageOutput(nb_image))
						mise_en_tab_ori(nb_image,largeur_image,Hauteur_image) ; apres ça l'image 16 millions de couleurs est dans le Tableau Tab_ori()
				StopDrawing()
				CopyArray(TAB_ori(), TAB())
				FlipBuffers()
				Case #Button_pick
				if IsImage(#image_ori)
						ClearScreen($0)
						CopyArray(TAB_ori(), TAB())
						CopyImage(#Image_ori,#Image)
						Flag_pick=-Flag_pick
						nbr_couleur=0
						if Flag_pick>0 ; mode on recup les couleurs
								;on nettoie le canvas qui contient la palette
								; StartDrawing(CanvasOutput(#image_palette))
								; Box(0,0,GadgetWidth(#image_palette),GadgetHeight(#image_palette),$0)
								; StopDrawing()
								
								; on nettoie aussi les listes concernant la palette
								ClearList(palette()) 
								ClearList(Des()) 
						Endif
				Endif
				Case #zone_acenseur
				;debug "ascenseur"
				; if IsImage(nb_image)
				; StartDrawing(ScreenOutput()) ;
				; DrawImage(ImageID(nb_image), 0, 0)
				; StopDrawing()
				; FlipBuffers()
				; Endif
				Case #CheckBox_Floyd
				statF=GetGadgetstate(#CheckBox_Floyd)
				if statf=#PB_CheckBox_Checked  
						floyd=1
				Else
						floyd=0
				Endif
				Case #CheckBox_Flou
				statfl=GetGadgetstate(#CheckBox_Flou)
				if statfl=#PB_CheckBox_Checked  
						Flou=1
				Else
						Flou=0
				Endif
				Case #TrackBar_tolerance
				tolerance=GetGadgetstate(#TrackBar_tolerance)
				SetgadgetText (#Text_tol_val,str(tolerance))
				Case #Text_tolerance
				Case #Text_Titre
				Case #Container_8
				Case #Button_Run
				if Flag_pick>0
						SetGadgetState(#Button_pick, 0)
						Flag_pick=-Flag_pick
				Endif
				if isimage(#image)
						;-bouton RUN
						if Flag_pick_pick=0  
								
								ClearList(palette()) 
								ClearList(Des()) 
								
								CopyArray(TAB_ori(), TAB())
								
						Endif
						ClearScreen($0)
						FlipBuffers()
						;Tolerance
						tolerance=GetGadgetstate(#TrackBar_tolerance)
						; Flou
						statfl=GetGadgetstate(#CheckBox_Flou)
						if statfl=#PB_CheckBox_Checked  
								Flou=1
						Else
								Flou=0
						Endif
						;FLoyd
						statF=GetGadgetstate(#CheckBox_Floyd)
						if statf=#PB_CheckBox_Checked  
								floyd=1
						Else
								floyd=0
						Endif
						; Nbr_couleur
						nbr_couleur=val(GetGadgetText(#String_nb_couleur))
						; Run
						palette=1; pour afficher la palette dans l'image
						if Flag_pick_pick=0 
								make_palette(#image,nbr_couleur,palette)
						Endif
						dessin(#image,nbr_couleur,tolerance,Floyd,flou ) ; 
				Else
						MessageRequester("info", "Chargez d'abord une image")
				ENdif
				Case #String_nb_couleur
				compteur_coul=0
				nbr_couleur=val(GetGadgetText(#String_nb_couleur))
				Case #Text_color
				Case #Button_Save
				if isimage(#image)
						SaveImage(#image,"resultat_en_"+str(nbr_couleur)+"_"+str(tolerance)+".bmp",#PB_ImagePlugin_BMP)
						MessageRequester("info", "Image sauvé avec le nom :"+chr(10)+"resultat_en_"+str(nbr_couleur)+"_"+str(tolerance)+".bmp")
				Else
						MessageRequester("info", "Chargez d'abord une image")
				Endif
		EndSelect
		; ////////////////////////
		Case #PB_Event_CloseWindow
		Select EventWindow()
				Case #Win
				CloseWindow(#Win)
				Break
		EndSelect
		Case #WM_LBUTTONDOWN
		
		if Flag_pick>0 ; on pick
				GetCursorPos_(@cp.POINT)
				GetWindowRect_(GadgetID(#Container_8),gr.RECT)
				PtInRect_(@gr, cp\x<<32+cp\Y)
				MapWindowPoints_(#Null, GadgetID(#Container_8), cp, 1) ; cp now contains gadget coords
				if ( cp\x>=0 and cp\x<=ImageWidth(#image)) and (cp\y>=0 and cp\y<=ImageHeight(#image) ) 
						StartDrawing(ScreenOutput()) ;
								couleur_pick=point(cp\x,cp\Y)
						StopDrawing()
						coul.i=couleur_pick
				Endif
				ForEach palette()
						if palette()=coul.i  ; c'est une couleurs nouvelle pour la palette ?                   
								flag_ok=1 ; non on l'a deja !
						Endif
				Next
				; *************************************************
				if flag_ok=1 ; couleur deja presente dans la palette
						flag_ok=0
				Else ; couleur nouvelle trouvée
						Flag_pick_pick=1
						AddElement(palette()) ; on la stock
						palette()=coul.i
						compteur_coul=compteur_coul+1
						nbr_couleur=compteur_coul
						SetGadgetText( #String_nb_couleur,str(nbr_couleur))
				Endif
				
				SortList(palette(), #PB_Sort_Descending)
				StartDrawing(CanvasOutput(#image_palette))
						
						Box(0,0,GadgetWidth(#image_palette),GadgetHeight(#image_palette),$0)
						compteur=0:vertical=0
						ForEach palette()
								pas=8
								
								Box (1+compteur,vertical,pas,pas,palette())
								compteur=compteur+pas
								
								if compteur => GadgetWidth(#image_palette)
										compteur=0
										vertical=vertical+pas
										compteur=0
								Endif
						Next 
						
				StopDrawing()
				
				
				
				
		Endif
EndSelect


if IsImage(#image)
		StartDrawing(ScreenOutput()) ;
				DrawImage(ImageID(#Image), 0, 0)
		StopDrawing()
		FlipBuffers()
Endif

Forever
;
;}
;-Procedures Zone
;-calcul Distance couleur
Procedure distance_couleur(couleur1,couleur2)
		; by Dobro
		rf.c=red(couleur1) :vf.c=green(couleur1): bf.c=blue(couleur1)
		r.c=red(couleur2) :v.c=green(couleur2): b.c=blue(couleur2)
		distance=sqr(pow(rf-r.c,2)+ pow(vf-v.c,2)+pow(bf-b.c,2)) ; calcul de la distance qui sépare la couleur de l'image avec la couleur de la palette
		ProcedureReturn distance
Endprocedure

;-make palette
Procedure make_palette(nb_image,nbr_couleur.i,palette)
		if nbr_couleur.i=0 :  nbr_couleur.i=16:Endif
		; By Dobro
		largeur_image=ImageWidth(nb_image)
		Hauteur_image=ImageHeight(nb_image)
		; mise en tableau
		StartDrawing(ImageOutput(nb_image))
				;mise_en_tab(nb_image,largeur_image,Hauteur_image) ; apres ça l'image 16 millions de couleurs est dans le Tableau Tab()
				RandomSeed(13)
				; ajout obligatoire du blanc, et du noir ! 
				AddElement(palette()) ; on la stock
				palette()=$0
				AddElement(palette()) ; on la stock
				palette()=rgb(255,255,255)
				ccc=0
				compteur_coul=0
				for i=1 to  nbr_couleur.i-2
				
						recommence:
						x=random(largeur_image-1,1) ; choisi x couleurs au hazard dans l'image pour fabriquer la palette
						y=random(Hauteur_image-1,1)
						
						; ici en principe, on est sur que 2 fois le meme pixel (et donc 2 fois la meme couleur, ne sera pas dans la palette
						coul.i=TAB(x,y) ; recupere la couleur dans l'image d'origine (celle des 16 millions de couleurs )
						; **** Scan la liste pour chercher des couleurs nouvelles **
						If nbr_couleur.i<=800
								tol=5
						Else
								Tol=1
						Endif
						ForEach palette()
								If distance_couleur(palette(),coul.i)<=Tol ; ICI on regarde si on a affaire a une nouvelle couleur , 
										; on considere que si la couleur trouvée est supérieur en distance  a : 5 , alors c'est une nouvelle couleur , sinon si c'est infereur, on considere qu'on a deja cette couleur dans la palette
										;if palette()=coul.i ; c'est une couleurs nouvelle pour la palette ?                   
										flag_ok=1 ; non on l'a deja !
										Break
								Endif
								ccco=ccco+1
								if ccco>nbr_couleur.i-2/3
										WaitWindowEvent(2)
										ccco=0
								Endif
						Next
						; *************************************************
						if flag_ok=1 ; couleur deja presente dans la palette
								flag_ok=0
								Goto recommence
						Else ; couleur nouvelle trouvée
								AddElement(palette()) ; on la stock
								palette()=coul.i
								compteur_coul=compteur_coul+1
						Endif
				Next i
				SortList(palette(), #PB_Sort_Descending)
				
				if palette=1 ; Dessine la palette
						pos=0:compteur=0:vertical=0
				StopDrawing() ; ferme l'ecran pour le moment
				StartDrawing(CanvasOutput(#image_palette))
						Box(0,0,GadgetWidth(#image_palette),GadgetHeight(#image_palette),$0)
						ForEach palette()
								if nbr_couleur.i<=512
										pas=8
								Else
										Pas=4
								Endif
								Box (1+compteur,vertical,pas,pas,palette())
								compteur=compteur+pas
								if compteur => GadgetWidth(#image_palette)
										compteur=0
										vertical=vertical+pas
								Endif
						Next
						compteur=0
						vertical=0
				StopDrawing()
				StartDrawing(ImageOutput(nb_image)) ; reouvre l'ecran
				Endif
				; a ce stade nous devrions avoir le bon nombre de couleurs
				; *************************************************
		StopDrawing()
		taa$= " il y a "+str(compteur_coul+2)+" couleurs dans la palette"
		taa1$= "ok la palette est créé j'attaque le dessin ... patience"
		SetgadgetText (#Text_info2,taa$+chr(10)+taa1$)
		
Endprocedure
;- Dessin
Procedure Dessin(nb_image,nbr_couleur,tolerance,Floyd,flou)
		DisableDebugger
		
		
		ClearScreen(0)
		FlipBuffers()
		largeur_image=ImageWidth(nb_image)
		Hauteur_image=ImageHeight(nb_image)
		FreeImage(nb_image) ; efface l'image pour etre sur d'avoir une nouvelle base
		CreateImage(nb_image, largeur_image,Hauteur_image) ; recreer l'image vierge
		taa2$= "debut du dessin"
		;SetgadgetText (#Text_info2,taa$+ " "+taa1$+ " "+taa2$)
		StartDrawing(ImageOutput(nb_image))
				For y=0 to Hauteur_image-1
						For x=0 to largeur_image-1
								coul.i=TAB(x,y)
								mem_distance=RGB(255,255,255)
								coull=$0
								; rf.c=red(coul.i)
								; vf.c=green(coul.i) 
								; bf.c=blue(coul.i)
								
								;if nbr_couleur>8
								ForEach palette() ; Pour chaque couleur de la palette
										;r.c=red(palette()) :v.c=green(palette()):b.c=blue(palette())
										distance=distance_couleur(coul.i,palette()) ; on regarde la distance qui separe la couleur d'origine de l'image avec la couleur en cours de la palette
										
										If distance<=mem_distance 					; si la distance trouvé est plus petite ou egale a la distance mise en memoire
												
												mem_distance=distance ; on prends cette couleur qui se rapproche de l'originale
												coull=palette()												
										Endif  ; a la fin , en principe on a la couleur de la palette qui se raproche le plus de la couleur du point original de l'image
										
										; Accelerateur si tolerance est grande ... mais image moins fidele
										If distance <=tolerance ; si la distance mesuré est inferieur au curseur de tolerance, on arrete la et on garde la derniere couleur de la palette trouvée
												Break
										Endif
										
								Next 
								plot(x,y,coull) ; dessine avec la couleur de la  palette en cours , en principe la couleur la plus proche du point d'origine
								mem_couleur=palette()
								
								compteur_activity=compteur_activity+1
								ccco=ccco+1
								if ccco=4000
										WaitWindowEvent(2)
										ccco=0
								Endif
						Next x
						taa$=str(compteur_activity/100)+"/"+str(largeur_image * Hauteur_image/100) ; affiche l'activité
						SetgadgetText (#Text_info,taa$)
				Next y
				taa$= "Fin dessin"
				SetgadgetText (#Text_info,taa$)
				SetgadgetText (#Text_info2,"")
				if Floyd=1 ; dessine le Floyd
				StopDrawing()
				mise_en_tab(nb_image,largeur_image,Hauteur_image)
				DoOmohundro(nb_image)
		Endif
		If Flou=1 ; ajoute du Flou
		StopDrawing()
		mise_en_tab(nb_image,largeur_image,Hauteur_image)
		Niveau=1
		Flou(nb_image,largeur_image,Hauteur_image, Niveau)
Endif
StopDrawing()
EnableDebugger
EndProcedure
;
Procedure mise_en_tab_ori(nb_image,Largeur_image,Hauteur_image)
		; By Dobro
		; mise en tableau du resultat de la reduction
		;;StartDrawing(ImageOutput(nb_image))
		For y=0 to Hauteur_image-1
				For x=0 to largeur_image-1
						TAB_ori(x,y)=point(x,y)
				Next x
		Next y
		;;StopDrawing()
EndProcedure
Procedure mise_en_tab(nb_image,Largeur_image,Hauteur_image)
		; By Dobro
		; mise en tableau du resultat de la reduction
		
		StartDrawing(ImageOutput(nb_image))
				For y=0 to Hauteur_image-1
						For x=0 to largeur_image-1
								TAB(x,y)=point(x,y)
						Next x
				Next y
		StopDrawing()
EndProcedure
Procedure Flou(nb_image,ImageX,ImageY, Niveau)
		; Le Soldat inconnu
		StartDrawing ( ImageOutput (nb_image)) ; on dessine sur l'image
				x = 0 ; on se place en x=0 sur l'image
				Repeat
						y = 0 ; on se place en y=0 sur l'image
						Repeat
								; on récupère la couleur du point en x et y et alentour
								Rouge = 0
								Vert = 0
								Bleu = 0
								NbPixel = 0
								For Px = -Niveau To Niveau
										For Py = -Niveau To Niveau
												If Px + x >= 0 And Px + x < ImageX
														If Py + y >= 0 And Py + y < ImageY
																; on fait le mélange des couleurs entre le point en x,y et ceux qui sont à sont alentour
																Couleur = TAB(Px + x, Py + y)
																Rouge = Rouge + Red (Couleur)
																Vert = Vert + Green (Couleur)
																Bleu = Bleu + Blue (Couleur)
																NbPixel + 1
														EndIf
												EndIf
										Next
								Next
								; On recalcule la nouvelle couleur
								Couleur = RGB (Rouge / NbPixel, Vert / NbPixel, Bleu / NbPixel)
								; si la taille du nouveau pixel est positive
								Plot (x, y, Couleur) ; on dessine un carré qui fait le nouveau pixel de la même couleur que celle récupéré en x et y
								; on se déplace sur l'image en y de la taille d'un pixel
								y = y + 1
						Until y >= ImageY ; si on a finit la colonne de l'image placé en x
						; on se déplace sur l'image en x de la taille d'un pixel
						x = x + 1
						; on fait progresser la barre
						;;;SetGadgetState ( #Barre , x)
				Until x >= ImageX ; si on a traité toutes les lignes de l'image
		StopDrawing ()
EndProcedure
Procedure DoOmohundro(hImg) ; Floyd
		Protected nextpixel.f, ierror.f, fer.f, eer.f, teer.f, lr.f
		StartDrawing(ImageOutput(hImg))
				width = ImageWidth(hImg): height = ImageHeight(hImg)
				Protected error.f         ;hold error for current pixel
				Dim error_arr.f(width)
				For y = 2 To height-3
						lr = 0
						For x = 2 To width-3     
								val = TruncF0255(RGBtoLum(Point(x,y)) + error_arr(x))
								If val > 128       
										Plot(x,y,TAB(x,y))     
										error = val-255
								Else
										r=red(TAB(x,y))/1.5
										v=green(TAB(x,y))/1.5
										b=blue(TAB(x,y))/1.5
										Plot(x,y,rgb(r,v,b))
										error = val
								EndIf           
								fer.f = error/4     ;a fourth of the error
								eer.f = fer/2       ;an eighth
								teer.f = fer + eer  ;three eights
								error_arr(x-1) + eer
								error_arr(x) = teer + lr
								lr = eer
								error_arr(x+1) + teer
						Next x
				Next y
		StopDrawing()
EndProcedure

Procedure.i TruncF0255 (a.f)
		If a > 255: a = 255: ElseIf a < 0: a = 0: EndIf
		ProcedureReturn a
EndProcedure
Procedure RGBtoLum(c.l)  ;Get luminosity (the min and max RGB levels / 2)
		r = (c & $FF) :  g = ((c & $FF00) >> 8) :  b = ((c & $FF0000) >> 16)
		If g < r: min = g: Else: min = r: EndIf
		If b < min: min = b: EndIf
		If g > r: max = g: Else: max = r: EndIf
		If b > max: max = b: EndIf
		If b > max: max = b: EndIf    
		lum = (max + min) >> 1  ;/ 2.0
		ProcedureReturn lum
EndProcedure

; Epb


Dernière modification par Zorro le jeu. 16/nov./2017 12:57, modifié 7 fois.
Image
Image
Site: http://michel.dobro.free.fr/
Devise :"dis moi ce dont tu as besoin, je t'expliquerai comment t'en passer"
Avatar de l’utilisateur
Zorro
Messages : 2185
Inscription : mar. 31/mai/2016 9:06

Re: Pure Reductor

Message par Zorro »

si on part de cette image :

Image

voici en 512 couleur Tolerance 0
Image

voici en 256 couleur Tolerance 0
Image

en 64 couleurs Tolerance 0
Image

en 16 Couleurs Tolerance 0
Image

En 8 Couleurs Tolerance 0
Image

En 4 couleurs Tolerance 0
Image

En 2 couleurs Tolerance 0
Image

:)
Dernière modification par Zorro le jeu. 16/nov./2017 11:56, modifié 5 fois.
Image
Image
Site: http://michel.dobro.free.fr/
Devise :"dis moi ce dont tu as besoin, je t'expliquerai comment t'en passer"
Avatar de l’utilisateur
SPH
Messages : 4722
Inscription : mer. 09/nov./2005 9:53

Re: Pure Reductor

Message par SPH »

En bleu, comme ca, on se croirait dans another world 8)
http://HexaScrabble.com/
!i!i!i!i!i!i!i!i!i!
!i!i!i!i!i!i!
!i!i!i!
//// Informations ////
Intel Core i7 4770 64 bits - GTX 650 Ti
Version de PB : 6.00 - 64 bits
Avatar de l’utilisateur
Zorro
Messages : 2185
Inscription : mar. 31/mai/2016 9:06

Re: Pure Reductor

Message par Zorro »

j'ai modifié mon code de Pure_Reductor

maintenant la tolérance marche bien mieux

donc si tolérance grande => traitement plus rapide mais image moins fidele
si Tolerance petite => Traitement plus lent , mais image Fidele !

Tolerance a 0 = image le plus fidele possible, mais tres lent sur Grosse image, ou avec un nobre de couleurs important (>256 )

bon test

Reedit (correction d'un bug lié a StarDrawing() )
Dernière modification par Zorro le mer. 15/nov./2017 12:56, modifié 1 fois.
Image
Image
Site: http://michel.dobro.free.fr/
Devise :"dis moi ce dont tu as besoin, je t'expliquerai comment t'en passer"
Mesa
Messages : 1093
Inscription : mer. 14/sept./2011 16:59

Re: Pure Reductor

Message par Mesa »

Y a un problème quelque part.

La photo originale ci-dessus fait 46.7ko.
Les traitements de zorro donnent des images très détériorées tout en restant autour de 40ko alors que le logiciel gratuit photofiltre donne une image sans aucune dégradation avec 16.2ko seulement ! Juste en réenregistrant la photo.
Il peut descendre jusqu'à 3.18ko avec une image qui se dégrade de plus en plus.

M.
Avatar de l’utilisateur
Zorro
Messages : 2185
Inscription : mar. 31/mai/2016 9:06

Re: Pure Reductor

Message par Zorro »

chez moi les images ne sont pas "déteriorées"
simplement elles perdent des couleurs , puisque c'est le but de ce prg

diminuer le nombre de couleur ....

j'etabli une palette
ensuite en fonction de la couleur d'un point de l'image original, je remplace par la couleur de la palette le plus proche de la couleur du point d'origine

voila c'est tout :)

ps j'ai reposté les images de François Hollande avec Bill Gate car les anciennes images ne correspondaient plus au code actuelle !

ce qui cause une différence avec un logiciel "Pro"
c'est qu'un soft Pro va analyser l'images et creer une palette intelligente

c'est au moment de la création de la palette que mon code peut effectivement "pecher" :)
Image
Image
Site: http://michel.dobro.free.fr/
Devise :"dis moi ce dont tu as besoin, je t'expliquerai comment t'en passer"
Avatar de l’utilisateur
Zorro
Messages : 2185
Inscription : mar. 31/mai/2016 9:06

Re: Pure Reductor

Message par Zorro »

j'ai un peu modifié mon code
pour qu'il fabrique une palette ayant un peut plus de differences (voir commentaire dans le code )

avant , je prenais des pixels au hasard dans l'image , si la couleur trouvé est nouvelle dans la palette
je l'ajoutais , et recommençais ainsi de suite pour les X couleurs de la palette (32 fois pour une palette de 32 couleurs )

maintenant, je prends les pixel au hasard dans l'image , mais si la couleur trouvée est nouvelle (avec une difference d'au moins 5 )
avec une couleur de la palette, alors seulement je la considere comme nouvelle couleur a intergrer dans la palette
sinon je recommence la tirage d'un pixel au hasard ...

du coup ça me donne une palette avec des couleurs qui ne peuvent pas etre trop proche (au moins 5 de distance d'eccart )
la palette deviens plus diverse !
on peut augmenter ce chiffre pour tester , ça se passe Ligne 374
mais il faut savoir qu'en diversifiant trop les couleur de la palette on perd aussi les transitions entre deux couleur (sur les dégradés par exemple )

j'ai mis 5 car ça me semble pas etre un trop mauvais compromis entre la diversité de la palette, et le respect des degradés (voir le Front de Hollande pour se rendre compte )

l'ensemble n'est pas trop rapide ... car plus on a de couleurs dans la palette , plus la comparaison pour dessiner avec une couleur proche
est longue, il faut regarder chaque couleur de la palette ....

c'est beaucoup plus rapide sur petite palette .....

mais en ayant focé la diversification des couleurs, j'ai un bien meilleur résultat sur les images au dessus de 200 couleurs
Image
Image
Site: http://michel.dobro.free.fr/
Devise :"dis moi ce dont tu as besoin, je t'expliquerai comment t'en passer"
Avatar de l’utilisateur
Ar-S
Messages : 9472
Inscription : dim. 09/oct./2005 16:51
Contact :

Re: Pure Reductor

Message par Ar-S »

Yo,
C'est vraiment pas mal pour les images < 8bits. En fait le résultat est aussi bon mais ton algo de couleur est plus fidèle donc l'image est plus ressemblante à l'originale.
De 8bits et + par contre, je trouve que le résultat via encodeimage() est plus propre. Un poil plus granuleux mais du coup sans cet effet de "blur" un peu trop prononcé sur ton image.
Bon job :)
~~~~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
GallyHC
Messages : 1703
Inscription : lun. 17/déc./2007 12:44

Re: Pure Reductor

Message par GallyHC »

Salut Zorro,

J'ai remarqué une choses sur les images de résultats, par rapport a celle d'origine. L'image est étirer verticalement, non?

Cordialement,
GallyHC
Configuration : Tower: Windows 10 (Processeur: i7 "x64") (Mémoire: 16Go) (GeForce GTX 760 - 2Go) - PureBasic 5.72 (x86 et x64)
Avatar de l’utilisateur
Zorro
Messages : 2185
Inscription : mar. 31/mai/2016 9:06

Re: Pure Reductor

Message par Zorro »

oui , ligne 139 -140 tu as

Code : Tout sélectionner

	if largeur_image>Hauteur_image : ResizeImage(#image,1024,768):endif
	if largeur_image<Hauteur_image : ResizeImage(#image,768,1024):endif
j'avais fait ça pour avoir mes images test en pleine interface :)

tu les commentes ; ça respectera exactement l'image d'origine (plus la resolution est grande, plus c'est lent bien sur :) )
Image
Image
Site: http://michel.dobro.free.fr/
Devise :"dis moi ce dont tu as besoin, je t'expliquerai comment t'en passer"
Répondre