Seite 1 von 1

DrawImage() ohne Smoothing

Verfasst: 19.05.2010 00:26
von NicTheQuick
Hallo Leute,

mir ist aufgefallen, dass DrawImage() ein automatisches Smoothing ausführt, wenn man die on-the-fly-Resize-Möglichkeit nutzt. Ich habe aber keinen Befehl gefunden, mit dem man das ausschalten kann. Mir reicht ein Resizing ohne Smoothing.
Außerdem wäre es praktisch, wenn es ein Äquivalent zu ClipSprite() für Images gäbe. Hat da jemand eine Idee?

Natürlich sollte das ganze cross-platform funktionieren.

Danke schonmal!

Re: DrawImage() ohne Smoothing

Verfasst: 19.05.2010 00:57
von AND51
Nur ResizeImage() unterstützt die Konstanten #PB_Image_Raw und #PB_Image_Smooth.
Andere native Möglichkeiten ein Bild, optional on-the-fly, zu resizen, sind mir derzeit nicht bekannt.

Re: DrawImage() ohne Smoothing

Verfasst: 19.05.2010 03:00
von NicTheQuick
Bei meiner Verwendung kann es durchaus vorkommen, dass ein anzuzeigendes Image um den Faktor 10000 gezoomt wird, aber nur ein 800x600 Ausschnitt daraus angezeigt wird. Deswegen wäre Clipping und Zoom on-the-fly am besten.

Re: DrawImage() ohne Smoothing

Verfasst: 19.05.2010 10:27
von #NULL
dazu gab's neulich ein feature request: http://www.purebasic.fr/english/viewtop ... 52&start=0
fände ich auch nützlich.

Re: DrawImage() ohne Smoothing

Verfasst: 19.05.2010 17:39
von #NULL
ich habe gerade bemerkt, dass selbst ResizeImage mit #PB_Image_Raw die farben verändert:

Code: Alles auswählen

InitSprite()
ww=300
wh=700
style | #PB_Window_ScreenCentered
style | #PB_Window_SystemMenu
style | #PB_Window_MinimizeGadget
hWin=OpenWindow(0, 50,100,ww,wh, "",style) :: AddKeyboardShortcut(0,#PB_Shortcut_Escape,10)
OpenWindowedScreen( hWin, 0,0,ww,wh, 0,0,0)

CreateImage(0,30,30)
StartDrawing(ImageOutput(0))
  DrawingMode(#PB_2DDrawing_Outlined)
  LineXY(1,1,28,28,$00ff00)
  LineXY(28,1,1,28,$0000ff)
  Circle(14,14,10,$ff0000)
StopDrawing()
SetClipboardImage(0)
CopyImage(0,1)
ResizeImage(1,200,200);,#PB_Image_Smooth)


Repeat
  event=WaitWindowEvent(30)
  em=EventMenu()
  Select event
    Case #PB_Event_CloseWindow
      quit=1
    Case #PB_Event_Menu
      Select em
      Case 10
        quit=1
      EndSelect
  EndSelect
  StartDrawing(ScreenOutput())
    DrawImage(ImageID(0),10,10)
    DrawImage(ImageID(0),10,110,200,200)
    DrawImage(ImageID(1),10,400);,200,200)
  StopDrawing()
  FlipBuffers()
  ClearScreen($333333)
Until quit
im Clipboard liegt dann das kleine originalbild, damit man es sich auch nochmal in einem anderen programm angucken kann.
bei mir sind beim 2. und 3. drawimage die farben nicht mehr rein, aber beide bilder sind identisch.
scheinbar benutzt DrawImage() auch 'raw', nur dass 'raw' eben nicht raw ist.

Re: DrawImage() ohne Smoothing

Verfasst: 19.05.2010 23:04
von PureLust
Hi Nic, ...

wenn es Dir bei Deiner Anfrage um eine möglichst hohe Geschwindigkeit ging - da hätte ich (natürlich) keine Lösung für.
Wenn es Dir aber nur um die Einfachheit ging (also alles mit einem bzw. zwei Befehl machen zu können) so hätte ich da zwei kleine Procs für Dich:

- ClipImage()
- DrawClippedImage()

Vielleicht kannst Du ja damit etwas anfangen:

Code: Alles auswählen

EnableExplicit

Structure ImageClip
	XPos.l
	YPos.l
	Width.l
	Height.l
	ImgID.i
EndStructure
 
Procedure InitClipImage()
	Global NewList ClippedImage.ImageClip()
	Global ClipImageInitialized = #True
EndProcedure
 
Procedure ClipImage(ImgID, XPos, YPos, Width, Height)
	If Not ClipImageInitialized : InitClipImage() : EndIf
	Protected ActImgID = #PB_Any
	ForEach ClippedImage()
		If ImgID = ClippedImage()\ImgID
			ActImgID = ImgID
			Break
		EndIf
	Next
	If ActImgID = #PB_Any
		AddElement(ClippedImage())
	EndIf
	ClippedImage()\XPos		= XPos
	ClippedImage()\YPos		= YPos
	ClippedImage()\Width		= Width
	ClippedImage()\Height	= Height
	ClippedImage()\ImgID		= ImgID
EndProcedure

Procedure DrawClippedImage(ImgID, XPos, YPos, Width=#PB_Ignore, Height=#PB_Ignore, ZoomMode=#PB_Image_Raw)
	Protected ActImgID = ImgID, DummyImg.i = #PB_Any
	If ClipImageInitialized
		ActImgID = #PB_Any
		ForEach ClippedImage()
			If ImgID = ClippedImage()\ImgID
				ActImgID = ImgID
				Break
			EndIf
		Next
		If ActImgID <> #PB_Any
			DummyImg	= GrabImage(ImgID, #PB_Any, ClippedImage()\XPos, ClippedImage()\YPos, ClippedImage()\Width, ClippedImage()\Height)
			If Not DummyImg : ProcedureReturn #False : EndIf
			If Width <> #PB_Ignore And Height <> #PB_Ignore
				ResizeImage(DummyImg, Width, Height, ZoomMode)
			ElseIf Width <> #PB_Ignore
				ResizeImage(DummyImg, Width, ClippedImage()\Height, ZoomMode)
			ElseIf Height <> #PB_Ignore
				ResizeImage(DummyImg, ClippedImage()\Width, Height, ZoomMode)
			EndIf
			ActImgID = DummyImg
		ElseIf (Width <> #PB_Ignore And Width <> ImageWidth(ImgID)) Or (Height <> #PB_Ignore And Height <> ImageHeight(ImgID))
			DummyImg	= CopyImage(ImgID, #PB_Any)
			If Not DummyImg : ProcedureReturn #False : EndIf
			If Width <> #PB_Ignore And Height <> #PB_Ignore
				ResizeImage(DummyImg, Width, Height, ZoomMode)
			ElseIf Width <> #PB_Ignore
				ResizeImage(DummyImg, Width, ClippedImage()\Height, ZoomMode)
			ElseIf Height <> #PB_Ignore
				ResizeImage(DummyImg, ClippedImage()\Width, Height, ZoomMode)
			EndIf
			ActImgID = DummyImg
		Else
			ActImgID = ImgID
		EndIf
	EndIf
	DrawImage(ImageID(ActImgID), XPos, YPos)
	If IsImage(DummyImg) : FreeImage(DummyImg) : EndIf
EndProcedure

; >>>>>>>>>> nachfolgend ein kleiner Beispiel-Code <<<<<<<<<<<<<<<

Define n

If CreateImage(0,200,200)
	If StartDrawing(ImageOutput(0))
		For n = 1 To 100
			Circle(Random(200), Random(200), Random(20), Random($ffffff))
		Next n
		StopDrawing()
	EndIf
EndIf
	
If OpenWindow(0,0,0,820,765,"Clipped Image Test",#PB_Window_ScreenCentered | #PB_Window_SystemMenu)
	If StartDrawing(WindowOutput(0))
		DrawImage(ImageID(0),0,0)
		For n = 1 To 8
			ClipImage(0,Random(130),Random(130), Random(30)+30, Random(30)+30)
			DrawClippedImage(0,(n-1)*103,230)									; Ohne Angabe von Width & Height wird der geclippte Bereich in Originalgröße gezeichnet
			DrawClippedImage(0,(n-1)*103,360,100,100)							; der geclippte Bereich wird auf 100 x 100 Pixel gezoomed
			ClipImage(0,Random(50),Random(50), Random(60)+90, Random(60)+90)
			DrawClippedImage(0,(n-1)*103,490)									; s.o.
			DrawClippedImage(0,(n-1)*103+20,620,60,60)						; geclippter Bereich wird OHNE Smoothing verkleinert
			DrawClippedImage(0,(n-1)*103+20,700,60,60,#PB_Image_Smooth)	; geclippter Bereich wird MIT  Smoothing verkleinert
		Next n
		DrawText(0,210," geclippte Ausschnitte in originaler Clip-Größe")
		DrawText(0,340," geclippte Ausschnitte auf 100x100 Pixel gezoomed (beim Zoomen ist smoothing ohne Wirkung)")
		DrawText(0,470," (neue) geclippte Ausschnitte in originaler Clip-Größe (diesmal größere Ausschnitte, da nachfolgend verkleinert wird)")
		DrawText(0,600," (neue) geclippte Ausschnitte auf 60x60 Pixel verkleinert - OHNE smoothing")
		DrawText(0,682," (neue) geclippte Ausschnitte auf 60x60 Pixel verkleinert - MIT  smoothing")
		StopDrawing()
	EndIf
	While WaitWindowEvent() <> #PB_Event_CloseWindow : Wend
EndIf
Wie immer - bei Fragen: Einfach fragen (da nur minimal dokumentiert) :mrgreen:

Gruß, PL.

[Nachtrag:]
Ich hab hier auch noch irgendwo zwei Procs rumfliegen, mit denen Du für ein und das selbe Bild verschiedene Clipping-Bereiche definieren kannst und Du dann direkt diese vorgegebenen Bereiche ausgeben kannst.

Die Procs hießen (glaube ich):
- DefineClipRegion()
- FreeClipRegion()
- DrawClipRegion()

Re: DrawImage() ohne Smoothing

Verfasst: 19.05.2010 23:14
von PureLust
#NULL hat geschrieben:ich habe gerade bemerkt, dass selbst ResizeImage mit #PB_Image_Raw die farben verändert:
Du hast in Deinem Code 'nen kleinen (Denk-)Fehler drin.

In Zeile 19 resized Du mit #PB_Image_Smooth, da dies der Default ist.
Richtig müsste es lauten:

Code: Alles auswählen

ResizeImage(1,200,200,#PB_Image_Raw)
Dann siehst Du bei den Vergrößerungen auch einen Unterschied.

Gruß, PL.

Re: DrawImage() ohne Smoothing

Verfasst: 20.05.2010 08:50
von NicTheQuick
Danke für die interessanten Procedures.
Aber da ich heute Nacht wegen Kaffee am Abend nicht schlafen konnte und mich mit Kopf-Rechnen und -Programmieren versucht habe in den Schlaf zu denken, ist mir eine bessere Idee gekommen, die gleichzeitig mein Überlappungsproblem verhindert. Hinzu kommt noch, dass ich gestern freak ins IRC bekommen habe und er mir hilfreiche Tipps gegeben hat, wie ich unter Linux mittels ImageID() direkt an die Pixeldaten komme. Es kann aber sein, dass ich das für meine neue Idee gar nicht mehr brauche. Also erstmal abwarten.

PS.: Habt ihr gewusst, dass 16 / 8.5 = 1.8823529411764705 ist? Das unterstrichene ist die Periode. Fragt besser nicht wie ich heute Nacht auf gerade diese Rechnung gekommen bin. :mrgreen:

Re: DrawImage() ohne Smoothing

Verfasst: 20.05.2010 09:23
von Christian H
NicTheQuick hat geschrieben: PS.: Habt ihr gewusst, dass 16 / 8.5 = 1.8823529411764705 ist? Das unterstrichene ist die Periode.
x/17 ist immer eine Periode.
http://www.mathlesstraveled.com/?p=160
http://www.google.de/search?num=50&hl=d ... =&gs_rfai=

Gruß Christian

Re: DrawImage() ohne Smoothing

Verfasst: 28.06.2010 20:47
von Vera
Hi NicTheQuick,

bin zufällig hier gelandetet und hatte unlängst auch mit einem ResizeImage - Problem zu tun. Dabei hab' ich entdeckt, dass man die beiden Parameter
#PB_Image_Smooth
#PB_Image_Raw

auch weg lassen und durch 0 und 1 bestimmen kann.

Dabei ergab sich aber auch, dass bei fehlender Parameterangabe immer ein smoothing durchgeführt wurde.
ResizeImage(1, new_size, new_size) -> smoothes
ResizeImage(1, new_size, new_size,0) -> smoothes
ResizeImage(1, new_size, new_size,1) -> doesn't smooth



@#NULL
mein angesprochenes Problem wurde letztlich erst bei CreateImage gelöst.
PureBasic geht bei fehlender Angabe, defaultmäßig von einer 24 bit Farbtiefe aus, erst mit der definitiven Angabe von 32 bit, waren dann die Ergebnisse wieder richtig.

CreateImage(0, size, size, 32)

würd' mich freu'n, wenn's weiter hilft :)

Grüße ~ Vera