Seite 1 von 2

ResizeImage

Verfasst: 29.07.2007 14:23
von pede
Hallo

Ich hab jetzt n kleines Problem mit ResizeImage.

Und zwar mach ich für mein Zeichenprogramm eine Zoom Funktion...
Ich wollte das mit ResizeImage machen, jedoch ergibt sich da das Problem, dass diese Funktion das Bild verändert :shock: , d.h. einige Linien werden heller, einige Pixel werden wieder weiß gemacht, obwohl sie schwarz waren ect...

Kann man diesen Fehler bei ResizeImage beheben, oder muss ich mir selbst ne Procedure zum verkleinern und vergrößern von Bildern machen?

PS: ein weiteres Problem ist, dass nachdem ich ein Bild abgespeichert habe(als BMP), und ich danach stark reinzoome, so ein komischer Rand da ist, kann man auch das beheben?

lg
pede

Verfasst: 29.07.2007 14:34
von ZeHa
Du kannst die Daten von der Anzeige trennen, sprich, das eigentliche Bild behältst Du immer irgendwo im Speicher. Auf den Bildschirm zeichnest Du aber nur eine Kopie. Sobald jemand Zeichenfunktionen ausführt, führst Du diese in Wirklichkeit auf das im Speicher befindliche Bild aus. Du kopierst allerdings alles wieder in das "Anzeige-Bild" und zeichnest das wieder auf den Bildschirm.

Das ist zumindest der Grundgedanke. Es gibt hier aber auch ein paar im Forum, die schon Zeichenprogramme geschrieben haben, die können Dir sicherlich detaillierter weiterhelfen :)

Verfasst: 29.07.2007 14:37
von pede
uups, vergessen, hier mal der Code:

Code: Alles auswählen

; PureBasic Visual Designer v3.95 build 1485 (PB4Code)

IncludeFile "Common_Groesse_Bild.pb"

;- Window Constants
;
Enumeration
  #Window_main
EndEnumeration

;- Gadget Constants
;
Enumeration 20
  #Image_gadget
  #Button_Neu
  #Button_Speichern
  #image1
  #Button_Farbe_Hintergrund
  #Button_Farbe_Zeichenstift
  #Checkbox_Kreis_Rechteck_Stift
  #Spin_Groesse_Stift
  #Text_Groesse_Stift
  #Button_Rueckgaengig
  #Radio_Punkt
  #Radio_LinieXY
  #Radio_Zusammenhang
  #Button_Groese_Bild
  #Popup_menu
  #zoom_in
  #Zoom_out
EndEnumeration

Dim image_save(10)

;-image_save belegen

i.b = 0
Repeat
    image_save(i) = i
    i = i + 1     
Until i = 10

i= 0   ; i muss wieder auf 0 (Start Save_image)

i_geaendert = 0      ; fürs Rückgängig machen


;- Meine Variablen
Structure Punkt
  x.l
  y.l
EndStructure

MausPos.Punkt       ; Positionen für Punktzeichnung

Klick_Pos_XY_1.Punkt  ;Positionen für die LinieXY      
Klick_Pos_XY_2.Punkt
erster_Punkt_XY.b = 1   ; checker ob erster oder 2. klick
zweiter_Punkt_XY = 0    ; erst sobald 2. Punkt gemacht, macht er Linie...

Klick_Pos_Zusammenhang_1.Punkt
Klick_Pos_Zusammenhang_2.Punkt
erster_Punkt_Zusammenhang.b = 1
zweiter_Punkt_Zusammenhang.b = 0

farbe_zeichenstift.l= RGB(0,0,0)   ;startet mit schwarz
Form_Stift.b = 0     ; Startet mit Rechteck....
Groesse_Stift.b = 10   ; Startet mit 10 Pixeln

Ende_Groesse_Bild = 0   ; checker ob das Parent Window geschlossen werden soll

gezoomed = 0        ; checken, welches Bild gezoomed wurde




CreateImage(#image1, 500, 500)
StartDrawing(ImageOutput(#image1))
Box(0,0 , 500, 500, RGB(255,255,255))
StopDrawing()

;CopyImage(#image1, #image_neu)

Procedure Open_Window_main()
  If OpenWindow(#Window_main, 216, 0, 834, 581, "imager",  #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_TitleBar )
    If CreateGadgetList(WindowID(#Window_main))
      ImageGadget(#Image_gadget, 40, 40, 520, 580, ImageID(#image1), #PB_Image_Border)
      ButtonGadget(#Button_Neu, 670, 460, 140, 40, "Neu")
      ButtonGadget(#Button_Speichern, 670, 520, 140, 40, "Speichern")
      ButtonGadget(#Button_Farbe_Hintergrund, 670, 380, 140, 40, "Farbe für Hintergrund wählen")
      ButtonGadget(#Button_Farbe_Zeichenstift, 670, 320, 140, 40, "Farbe für Stift wählen")
      CheckBoxGadget(#Checkbox_Kreis_Rechteck_Stift, 670, 280, 180, 30, "Stift hat Kreisform")
      SpinGadget(#Spin_Groesse_Stift, 670, 240, 40, 25, 1, 100)
      SetGadgetState(#Spin_Groesse_Stift, 10)
      SetGadgetText(#Spin_Groesse_Stift, "10")
      TextGadget(#Text_Groesse_Stift, 720, 245, 100, 30, "Größe des Stifts")
      ButtonGadget(#Button_Rueckgaengig, 670, 180, 100, 40, "Rückgängig")
      OptionGadget(#Radio_Punkt, 670, 140, 180, 20, "Punkt")
      SetGadgetState(#Radio_Punkt, 1)    ; Standart mäßig Punkt aktivieren
      OptionGadget(#Radio_LinieXY, 670, 110, 180, 20, "LinieXY")
      OptionGadget(#Radio_Zusammenhang, 670, 80, 180, 20, "Zusammenhängende Linien")
      ButtonGadget(#Button_Groese_Bild, 670, 30, 150, 40, "Größe des Bildes in Pixel")
      If CreatePopupMenu(#Popup_menu)
             MenuItem(#Zoom_in, "Zoom in")
             MenuItem(#Zoom_out, "Zoom out")
             
          
      GadgetToolTip(#Radio_LinieXY, "Klicken Sie zwei mal ins Bild, die beiden Klickpunkte werden dann mit einer Linie verbunden")
            
      EndIf
     EndIf
      
    EndIf

EndProcedure

Open_window_main()
;-                                                                                
Repeat
  event= WaitWindowEvent()
    Select event
    
       Case #PB_Event_Gadget
       
          Select EventGadget()
          
             Case #image_gadget
             
                Select EventType()
                
                    Case #PB_EventType_LeftClick
                        ;Hier steht für ResizeImage unwichtiger Code
                
                    Case #PB_EventType_RightClick
                          DisplayPopupMenu(#Popup_menu, WindowID(#window_main))
                        
                        
                EndSelect
             
             ;-Speichern   
             [b]Case #Button_Speichern
             
                  ;Falls gezoomed wurde, zurückzoomen
                  If gezoomed
                      ResizeImage(#image1, Bild_groesse_x, Bild_groesse_y, #PB_Image_Raw)                  
                  EndIf
                  
                  Datei_speichern$=SaveFileRequester("Wo soll die Datei gespeichert werden?", "C:\" , " (*.bmp) | *.bmp", 0) 
                  Datei_speichern$ = Datei_speichern$ + ".bmp"
                  If Datei_speichern$
                    SaveImage(#image1, Datei_speichern$)
                    
                    If gezoomed            ; wieder rückgängig zoomen
                        ResizeImage(#image1, x_gezoomed, y_gezoomed, #PB_Image_Raw)
                        SetGadgetState(#image_gadget, ImageID(#image1))
                    EndIf 
                    
                  Else
                    MessageRequester("Fehler", "Sie haben keine Datei ausgewählt!")
                  EndIf
                  gezoomed = 0    ; wieder auf 0 setzen
                  [/b]             ;-neu     
             Case #Button_Neu
             
                erster_Punkt_XY = 1    ; damit beim nächsten Mal wieder der 1. Punkte gespeichert wird
                zweiter_Punkt_XY = 0
                
                erster_Punkt_Zusammenhang = 1 ; vom Radio Button Zusammenhang, erster Punkt muss neu gesetzt werden
                zweiter_Punkt_Zusammenhang = 0
                StartDrawing(ImageOutput(#image1))
                Box(0,0, 600, 500, RGB(255,255,255))
                StopDrawing()
                SetGadgetState(#image_gadget, ImageID(#image1))
             
             ;auch unwichtig für resizeImage           ;-                                           
           Case #Button_Groese_Bild
           
           Open_Window_Groesse_Bild()
           DisableWindow(#Window_main, 1)
           
           Repeat
              event_Bild_groesse = WaitWindowEvent()
              ;Debug "bkub"
              Select event_Bild_groesse
                  
                  Case #PB_Event_Gadget
                  
                      Select EventGadget()
                      
                          Case #Button_OK
                          
                              Bild_groesse_x$ = GetGadgetText(#String_Groesse_Bild_x)
                              Bild_groesse_y$ = GetGadgetText(#String_Groesse_Bild_y)
                      
                              Bild_groesse_x = Val(Bild_groesse_x$)
                              Bild_groesse_y = Val(Bild_groesse_y$)
                              
                              If Bild_groesse_x < 601 And Bild_groesse_y < 501
                                CreateImage(#image1, Bild_groesse_x, Bild_groesse_y)
                                StartDrawing(ImageOutput(#image1))
                                Box(0,0 , Bild_groesse_x, Bild_groesse_y, RGB(255,255,255))
                                StopDrawing()
                              Else
                                MessageRequester("Fehler", "Das Bild ist zu groß")
                              EndIf
                              
                              Ende_Groesse_Bild = 1
                          
                      EndSelect
                      
                  Case #PB_Event_CloseWindow
                        Ende_Groesse_Bild = 1
                                    
              EndSelect                
                             
           Until Ende_Groesse_Bild = 1
           
           Ende_Groesse_Bild = 0  ; falls nochmal aufgerufen, dass prog nicht sofort wieder raus geht
           
           CloseWindow(#Window_Groesse_Bild)
           DisableWindow(#Window_main, 0)
           
           SetGadgetState(#image_gadget, ImageID(#image1))
      
          EndSelect
          
       ;-PopupMenü    
       Case #PB_Event_Menu
             Select EventMenu()
                     [b]Case #Zoom_in
                          gezoomed = 1  ; checkt dass gezoomed wurde (fürs speichern)
                          If Bild_groesse_x = Bild_groesse_y          ; Bild ist quadratisch
                              x_gezoomed = 500
                              y_gezoomed = 500
                              ResizeImage(#image1, x_gezoomed, y_gezoomed, #PB_Image_Raw)
                              SetGadgetState(#Image_gadget, ImageID(#image1))
                              
                              
                          ElseIf Bild_groesse_x > Bild_groesse_y       ; x ist die längere Seite
                              Verhaeltnis_x = 600/Bild_groesse_x     ; um dieses Verhältnis wurde x vergrößert
                              x_gezoomed = 600
                              y_gezoomed = Bild_groesse_y * Verhaeltnis_x
                              ResizeImage(#image1, x_gezoomed, y_gezoomed, #PB_Image_Raw)
                              SetGadgetState(#Image_gadget, ImageID(#image1))
                              
                              
                          ElseIf Bild_groesse_y > Bild_groesse_x       ; y ist die längere Seite
                              Verhaeltnis_y = 500/Bild_groesse_y
                              x_gezoomed = Bild_groesse_x * Verhaeltnis_y
                              y_gezoomed = 500
                              ResizeImage(#image1, x_gezoomed, y_gezoomed, #PB_Image_Raw)
                              SetGadgetState(#Image_gadget, ImageID(#image1))
                              
                              
                          EndIf
                          
                     Case #Zoom_out
                        ResizeImage(#image1, Bild_groesse_x, Bild_groesse_y)
                        SetGadgetState(#Image_gadget, ImageID(#image1))    [/b]
          
             EndSelect
             
       EndSelect ;Event      

Until Event = #PB_Event_CloseWindow

ich kann auch gern das ganze überflüssige rausnehmen...

Verfasst: 29.07.2007 14:42
von uweb
ZeHa's Tipp setze ich mal voraus.

Ich habe zwar keine Erfahrung damit, aber nach einem Blick in die Hilfe einen Verdacht. Hast Du den optionale Modus-Parameter (#PB_Image_Raw) verwendet ?

#PB_Image_Smooth
Änderung der Bildgröße mit Kantenglättung ("smoothing")
Standard, wenn 'Modus' nicht angegeben wird.

#PB_Image_Raw
Änderung der Bildgröße ohne jegliche Interpolation.


Wenn ja habe ich noch einen weiteren Verdacht :
Du wirst vermutlich mit ungeradem Zoomfaktor arbeiten. Wenn z.B. aus 2 Pixeln (rot und blau) drei gemacht werden sollen - welche Farben sollen die dann haben ?

PS
Deinen Code habe ich erst nach meinem senden gesehen. Aber, uups (IncludeFile "Common_Groesse_Bild.pb" ... Case #Button_Speichern ), es wäre nett gewesen es uns etwas leichter zu machen. Ich schauen ihm mir gleich trotzdem an.

PPS
Wenn ich es richtig sehe lag ich mit meinem zweiten Verdacht richtig. Richtig ?

Verfasst: 29.07.2007 14:56
von pede
jo #PB_Image_Raw hab ich immer verwendet...

das mit den Pixeln hab ich mir auch schon überlegt, erklärt aber noch nicht, wieso so ein komischer rand gemacht wird, und wieso durchs zoomen GANZE linien heller werden, das kann doch höchstens bei ein paar Pixeln passieren?

Verfasst: 29.07.2007 15:02
von uweb
Probiere es doch einfach mal mit 200, 400, usw. DU hast den lauffähigen Code, nicht ich. Ich sehe den komischen Rand also nicht. Wenn es so nicht läuft wäre es hilfreich einen einfachen Dummy zu schreiben bei dem das Bild erzeugt wird. Dann sehen und besprechen alle das Gleiche.

Verfasst: 29.07.2007 15:21
von Kaeru Gaman
das kommt auch auf die routinen drauf an, die zum resizen benutzt werden...
wenn das im grunde ein API call ist... wer weiß?

also, wenn man in paint ein bild mehrfach vergrößert, verkleinert, vergrößert, usw. ein paar mal,
kann man sehen, wie sich die farbnuancen komplett ändern.
..und Paint nutzt doch die standard-calls...

und wie uweb sagte...
wir sehen weder bild noch code.

wenn du mal zwei bilder vorher/nachher postest, können wir dazu auch was sagen.

und wie sind die größenverhältnisse?
also, wie hoch/breit ist das Image vorher, und welche höhe/breite gibst du beim ResizeImage-Befehl an?

Verfasst: 29.07.2007 17:25
von PureLust
pede hat geschrieben:Und zwar mach ich für mein Zeichenprogramm eine Zoom Funktion...
Da Dein Code mangels benötigter Dateien nicht so ohne weiters lauffähig ist konnte ich ihn nicht testetn bzw. nicht genau ersehen was er machen soll.

Da Du aber von einem "Zeichen"-Programm redest, gehe ich da recht in der Annahme, dass Du die Linien, Kreise etc. auf dem Bildschirm selber zeichnest - es also eine Art CAD-Programm sein soll?
Dass Du also die Informationen welche Linien/Kreise in welcher Größe an welche Position kommen in Deinem Programm gespeichert hast?

Somit musst Du für eine Zoom-Funktion nicht das gezeichnete Bild vergrößern bzw. verkleinern, sondern die Linien/Kreise einfach neu zeichnen und dabei den Zoomfaktor mit einberechnen.

Bsp:

Code: Alles auswählen

Zoom.f = 1.2
LineXY(x1 * Zoom, y1 * Zoom, x2 * Zoom, y2 * Zoom)
Wenn Du den gezoomten Ausschnitt auch noch verschieben möchtest müsstest Du noch eine Offset-Koordinate mit einbeziehen mit deren Hilfe Du den Ausschnitt verschieben kannst:

Code: Alles auswählen

Zoom.f = 1.2
XOffset = 30
YOffset = 50
LineXY(x1 * Zoom - XOffset, y1 * Zoom - YOffset, x2 * Zoom - XOffset, y2 * Zoom - YOffset)

Verfasst: 30.07.2007 05:35
von PureLust
@pede:

da ich momentan ohnehin etwas Langeweile hatte, hab ich Dir für den Fall das ich mit meiner o.G. Vermutung richtig lag (also dass Du ein CAD-ähnliches Programm machen wolltest) mal eine kleine Demo gemacht bei der Du den Arbeitsbereich zoomen und den Ausschnitt verschieben kannst.
Damit man per MouseWheel zoomen kann ist die Demo jedoch auf Screen-Basis und nicht auf Image-Basis aufgebaut.

Bild

Code: Alles auswählen

EnableExplicit
Structure DrawFigure
	type.b
	x1.w
	y1.w
	x2.w
	y2.w
	col.l
EndStructure

#MaxFigures    = 30
#DisplayWidth  = 800
#DisplayHeight = 600
Define n, Quit = #False
Define CenterX.f = #DisplayWidth / 2
Define CenterY.f = #DisplayHeight / 2
Define Zoom.f = 1, ActZoom.f
Define OldCenterX.f, OldCenterY.f, OldZoom.f
Define MinCenterX = -100, MaxCenterX = #DisplayWidth+100
Define MinCenterY = -100, MaxCenterY = #DisplayHeight+100
Global Dim figure.DrawFigure(#MaxFigures)
For n = 0 To #MaxFigures-1		; Create random figures
	figure(n)\type = Random(2)
	figure(n)\x1   = Random(MaxCenterX) + MinCenterX
	figure(n)\y1   = Random(MaxCenterY) + MinCenterY
	Select figure(n)\type
		Case 0		; shape is line
			figure(n)\x2   = Random(MaxCenterX) + MinCenterX
			figure(n)\y2   = Random(MaxCenterY) + MinCenterY
		Case 1		; shape is box
			figure(n)\x2   = Random(MaxCenterX) + MinCenterX - figure(n)\x1
			figure(n)\y2   = Random(MaxCenterY) + MinCenterY - figure(n)\y1
		Case 2		; shape is circle
			figure(n)\x2   = Random(MaxCenterY / 4) + Abs(MinCenterX / 4)
	EndSelect
	figure(n)\col  = Random($ffffff) & $f0f0f0 | $0f0f0f
Next n

Procedure RedrawGraph()
	Protected n
	Shared CenterX, CenterY, Zoom
	ClearScreen(0)
	If StartDrawing(ScreenOutput())
		DrawingMode(#PB_2DDrawing_Transparent | #PB_2DDrawing_Outlined)
		For n = 0 To #MaxFigures-1
			Select figure(n)\type
				Case 0		; shape is line
					LineXY((figure(n)\x1 - CenterX) * Zoom + #DisplayWidth/2, (figure(n)\y1 - CenterY) * Zoom + #DisplayHeight/2, (figure(n)\x2 - CenterX) * Zoom + #DisplayWidth/2, (figure(n)\y2 - CenterY) * Zoom + #DisplayHeight/2, figure(n)\col)
				Case 1		; shape is box
					Box((figure(n)\x1 - CenterX) * Zoom + #DisplayWidth/2, (figure(n)\y1 - CenterY) * Zoom + #DisplayHeight/2, figure(n)\x2 * Zoom, figure(n)\y2 * Zoom, figure(n)\col)
				Case 2		; shape is circle
					Circle((figure(n)\x1 - CenterX) * Zoom + #DisplayWidth/2, (figure(n)\y1 - CenterY) * Zoom + #DisplayHeight/2, figure(n)\x2 * Zoom, figure(n)\col)
			EndSelect
		Next n
		DrawText(5, 5,"X-Center: "+Str(CenterX),$888888)
		DrawText(5,25,"Y-Center: "+Str(CenterY),$888888)
		DrawText(5,45,"Zoom    : "+StrF(Zoom,2),$888888)
		StopDrawing()
		FlipBuffers()
	EndIf
EndProcedure

If Not InitSprite() Or Not InitKeyboard() Or Not InitMouse() : End : EndIf
If OpenWindow(0,0,0,#DisplayWidth,#DisplayHeight,"CAD-Demo  (use Mouse to move, MouseWheel to zoom, ESC to exit)",#PB_Window_ScreenCentered)
	If OpenWindowedScreen(WindowID(0),0,0,#DisplayWidth,#DisplayHeight,0,0,0)
		Repeat
			While WindowEvent() : Wend
			ExamineKeyboard()
			If KeyboardPushed(#PB_Key_Escape) : Quit = #True : EndIf
			ExamineMouse()
			CenterX + MouseDeltaX()/Zoom : If CenterX < MinCenterX : CenterX = MinCenterX : ElseIf CenterX > MaxCenterX : CenterX = MaxCenterX  : EndIf
			CenterY + MouseDeltaY()/Zoom : If CenterY < MinCenterY : CenterY = MinCenterY : ElseIf CenterY > MaxCenterY : CenterY = MaxCenterY : EndIf
			If MouseWheel() <> 0 And Zoom - MouseWheel() / 10 <= 4 And Zoom - MouseWheel() / 10 >= 0.5
				Zoom - MouseWheel() / 10
			EndIf
			If OldCenterX <> CenterX Or OldCenterY <> OldCenterY Or OldZoom <> Zoom
				OldCenterX = CenterX
				OldCenterY = CenterY
				OldZoom = Zoom
 				RedrawGraph()
			Else
				Delay(10)
			EndIf
		Until Quit
		CloseScreen()
	EndIf
	CloseWindow(0)
EndIf
Vielleicht kannst Du ja was damit anfangen.

Gruß, PL.

Verfasst: 30.07.2007 08:53
von pede
erstmal danke für die Antworten bis jetzt, und auch dir danke PureLust für das Programm.

Mit Zeichenprogramm meinte ich sowas wie Paint...

hier mal n paar Fotos:

1)Hier habe ich das Bild in einer Auflösung von 100 * 50 gezeichnet

Bild

2)Hier habe ich reingezoomt
Bild

3)Hier habe ich im gezoomten eine Linie gezeichnet, dann wieder auf orginalgröße gezoomt (Linie ist grau geworden), dann wieder gezoomt und dann nochmal ne vergleichslinie gemacht, die schwarz ist...

Bild


Und hier das Randproblem:

Bild



...