Ermitteln der Imagegröße eines CanvasGadgets?
Ermitteln der Imagegröße eines CanvasGadgets?
Hallo,
ich habe gerade das Problem, dass ich das Image eines CanvasGadgets ersetzen möchte und dazu die exakte Größe des dafür nötigen Images suche. Das CanvasGadget hat einen Rahmen und dieser wird offenbar vom Darstellungsbereich abgezogen.
Über GadgetWidth() und GadgetHeight() bekomme ich die äußeren Maße des Gadgets. Diese Werte sind durch den Rahmen größer als das angezeigte Image. Unter Win 10 sind das z.B. 4 Pixel in jede Richtung.
Nun möchte ich aber nicht mit festen Werten arbeiten (ImageWidth = GadgetWidth() - 4), da diese evtl. von OS zu OS unterschiedlich sind. Gibt es eine Möglichkeit die tatsächlichen Ausmaße des Canvas-Images zu ermitteln?
Mit GetGadgetAttribute(MeinCanvasGadget, #PB_Canvas_Image) bekomme ich leider das Image(Windows-)handle zurück, welches nicht mit ImageWidth() funktioniert.
PS: Dann habe ich noch eine Verständnisfrage.
Ich möchte aus einem großen Image (z.B. 600 x 600 pixel) beim Drüberfahren mit der Maus einen 40 x 40 pixel großen Bereich herauskopieren, um ihn in einem separaten ImageGadget anzuzeigen. Das ganze passiert also bei jedem MouseMove-Event auf dem Canvas, unter Umständen also x mal pro Sekunde.
Frage: Ist der richtige Weg dies zu tun folgender?
1) NeuesImage = GrabImage(#CanvasImage, #PB_Any, MouseX, MouseY, 40, 40)
2) SetGadgetState(#ImageGadget, ImageID(NeuesImage))
Wenn das der richtige Weg ist, muss ich "NeuesImage" dann noch freigeben?
Vom Gefühl her würde ich es eher so machen, dass nicht x mal pro Sekunde ein neues Image generiert wird, sondern hätte gedacht, dass man irgendwie die Pixeldaten von einem Image zum einem anderen, bereits vorhandenen Image kopiert. Dazu habe ich in der Befehlsreferenz allerdings nichts gefunden.
ich habe gerade das Problem, dass ich das Image eines CanvasGadgets ersetzen möchte und dazu die exakte Größe des dafür nötigen Images suche. Das CanvasGadget hat einen Rahmen und dieser wird offenbar vom Darstellungsbereich abgezogen.
Über GadgetWidth() und GadgetHeight() bekomme ich die äußeren Maße des Gadgets. Diese Werte sind durch den Rahmen größer als das angezeigte Image. Unter Win 10 sind das z.B. 4 Pixel in jede Richtung.
Nun möchte ich aber nicht mit festen Werten arbeiten (ImageWidth = GadgetWidth() - 4), da diese evtl. von OS zu OS unterschiedlich sind. Gibt es eine Möglichkeit die tatsächlichen Ausmaße des Canvas-Images zu ermitteln?
Mit GetGadgetAttribute(MeinCanvasGadget, #PB_Canvas_Image) bekomme ich leider das Image(Windows-)handle zurück, welches nicht mit ImageWidth() funktioniert.
PS: Dann habe ich noch eine Verständnisfrage.
Ich möchte aus einem großen Image (z.B. 600 x 600 pixel) beim Drüberfahren mit der Maus einen 40 x 40 pixel großen Bereich herauskopieren, um ihn in einem separaten ImageGadget anzuzeigen. Das ganze passiert also bei jedem MouseMove-Event auf dem Canvas, unter Umständen also x mal pro Sekunde.
Frage: Ist der richtige Weg dies zu tun folgender?
1) NeuesImage = GrabImage(#CanvasImage, #PB_Any, MouseX, MouseY, 40, 40)
2) SetGadgetState(#ImageGadget, ImageID(NeuesImage))
Wenn das der richtige Weg ist, muss ich "NeuesImage" dann noch freigeben?
Vom Gefühl her würde ich es eher so machen, dass nicht x mal pro Sekunde ein neues Image generiert wird, sondern hätte gedacht, dass man irgendwie die Pixeldaten von einem Image zum einem anderen, bereits vorhandenen Image kopiert. Dazu habe ich in der Befehlsreferenz allerdings nichts gefunden.
"Never run a changing system!" | "Unterhalten sich zwei Alleinunterhalter... Paradox, oder?"
PB 6.02 x64, OS: Win 7 Pro x64 & Win 11 x64, Desktopscaling: 125%, CPU: I7 6500, RAM: 16 GB, GPU: Intel Graphics HD 520
Useralter in 2024: 56 Jahre.
PB 6.02 x64, OS: Win 7 Pro x64 & Win 11 x64, Desktopscaling: 125%, CPU: I7 6500, RAM: 16 GB, GPU: Intel Graphics HD 520
Useralter in 2024: 56 Jahre.
- man-in-black
- Beiträge: 362
- Registriert: 21.08.2006 17:39
Re: Ermitteln der Imagegröße eines CanvasGadgets?
Hi,
kann dir da nicht groß helfen, aber wie wäre es mit einem zweiten Canvas, auf dem du das Bild einfach clipst?
Canvas1 ist dann das Original, zuständig für Hover ... und Canvas2 verschiebt sein dargestelltes Bild in einem 40x40 Viewport.
Und zu deinen Dimensionen. Hilft OutputHeight() vielleicht? Habs jetzt nicht getestet, erinnere mich aber an einen anderen Thread.
MFG
MIB
kann dir da nicht groß helfen, aber wie wäre es mit einem zweiten Canvas, auf dem du das Bild einfach clipst?
Canvas1 ist dann das Original, zuständig für Hover ... und Canvas2 verschiebt sein dargestelltes Bild in einem 40x40 Viewport.
Und zu deinen Dimensionen. Hilft OutputHeight() vielleicht? Habs jetzt nicht getestet, erinnere mich aber an einen anderen Thread.
MFG
MIB
Re: Ermitteln der Imagegröße eines CanvasGadgets?
Direkt aus dem jaPBe Quellcode... (naja fast, da gabs kein Protected ^^ ) :
Hier werden die Ausmaße einer Bitmap zurückgegeben (also dein OS-Handle).
Ich denke das hast du jetzt gesucht.
Nachtrag :
Wenn Du #PB_Any zum erstellen nutzt, musst du freigeben. Bei einer festen Nummernvergabe nicht.
Dann kann man einfach "überschreiben". (Liegt an #PB_Any das extrem hohe Nummern vergibt)
Code: Alles auswählen
Procedure GetBitmapWidth(hBitmap)
Protected BmpInfo.BITMAP
If hBitmap = 0 : ProcedureReturn 0 : EndIf
If GetObjectType_(hBitmap) <> #OBJ_BITMAP : ProcedureReturn 0 : EndIf
If GetObject_(hBitmap, SizeOf(BITMAP), BmpInfo) = 0 : ProcedureReturn 0 : EndIf
ProcedureReturn BmpInfo\bmWidth
EndProcedure
Procedure GetBitmapHeight(hBitmap)
Protected BmpInfo.BITMAP
If hBitmap = 0 : ProcedureReturn 0 : EndIf
If GetObjectType_(hBitmap) <> #OBJ_BITMAP : ProcedureReturn 0 : EndIf
If GetObject_(hBitmap, SizeOf(BITMAP), BmpInfo) = 0 : ProcedureReturn 0 : EndIf
ProcedureReturn BmpInfo\bmHeight
EndProcedure
Ich denke das hast du jetzt gesucht.
Nachtrag :
Wenn Du #PB_Any zum erstellen nutzt, musst du freigeben. Bei einer festen Nummernvergabe nicht.
Dann kann man einfach "überschreiben". (Liegt an #PB_Any das extrem hohe Nummern vergibt)
PureBasic 6.10 LTS (Windows x86/x64) | Windows10 Pro x64 | Asus TUF X570 Gaming Plus | R9 5900X | 64GB RAM | GeForce RTX 3080 TI iChill X4 | HAF XF Evo | build by vannicom
- ts-soft
- Beiträge: 22292
- Registriert: 08.09.2004 00:57
- Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel - Wohnort: Berlin
Re: Ermitteln der Imagegröße eines CanvasGadgets?
Sind ja auch Speicheradressen!Bisonte hat geschrieben:(Liegt an #PB_Any das extrem hohe Nummern vergibt)
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Re: Ermitteln der Imagegröße eines CanvasGadgets?
Danke Bisonte, die Prozeduren funktionieren einwandfrei.
Mit dem Grabben habe ich es jetzt so gelöst.
Das funktioniert, ist aber halt eine ewige "GrabImage / FreeImage" Orgie.
Da ich die Image-Lib Internas nicht kenne, kann ich nicht beurteilen, wie groß der Overhead beim hochfrequenten Neuerstellen eines Images ist.
Wie gesagt, logischer wäre für mich, wenn man den BitmapInhalt eines Images in die Bitmap eines anderen Images kopieren könnte (ggf. auch als Ausschnitt) ohne dabei jedes mal ein drittes Image als temporären "Datenträger" benutzen zu müssen. Aber das scheint mit PB-eigenen Mitteln nicht zu gehen.
Mit dem Grabben habe ich es jetzt so gelöst.
Code: Alles auswählen
If StartDrawing(CanvasOutput(Window_Screenshot_Canvas_Screenshot))
iImageClip = GrabDrawingImage(#PB_Any, x, y, iImageWidth, iImageHeight)
StopDrawing()
EndIf
If iImageClip = 0 : ProcedureReturn : EndIf
SetGadgetState(Window_Screenshot_Image_Screenshot, ImageID(iImageClip))
FreeImage(iImageClip)
Da ich die Image-Lib Internas nicht kenne, kann ich nicht beurteilen, wie groß der Overhead beim hochfrequenten Neuerstellen eines Images ist.
Wie gesagt, logischer wäre für mich, wenn man den BitmapInhalt eines Images in die Bitmap eines anderen Images kopieren könnte (ggf. auch als Ausschnitt) ohne dabei jedes mal ein drittes Image als temporären "Datenträger" benutzen zu müssen. Aber das scheint mit PB-eigenen Mitteln nicht zu gehen.
"Never run a changing system!" | "Unterhalten sich zwei Alleinunterhalter... Paradox, oder?"
PB 6.02 x64, OS: Win 7 Pro x64 & Win 11 x64, Desktopscaling: 125%, CPU: I7 6500, RAM: 16 GB, GPU: Intel Graphics HD 520
Useralter in 2024: 56 Jahre.
PB 6.02 x64, OS: Win 7 Pro x64 & Win 11 x64, Desktopscaling: 125%, CPU: I7 6500, RAM: 16 GB, GPU: Intel Graphics HD 520
Useralter in 2024: 56 Jahre.
Re: Ermitteln der Imagegröße eines CanvasGadgets?
Wie gesagt. Wenn Du eine feste PB Objektnummer wählst, anstelle von #PB_Any, kannst du laufend "überschreiben". ohne freigabe des vorherigen Bildes.
Also die GrabImage Variante ist mit GrabImage(#CanvasImage, #ImageAusschnitt, MouseX, MouseY, 40, 40) noch am sinnvollsten (von der Logik her)
Kein Ewiges erstellen und freigeben, sondern überschreiben.
P.S.
Wobei ich gerade die Idee hatte, anstelle eines ImageGadgets ein Canvas zu nehmen und dort einfach nur versetzt zu zeichnen. so wie z.B. Ein Grosses Bild liegt unter einem kleinen ausschnitt und wird bewegt...
Dann nur noch die Koordinaten berechnen und an das kleinere Canvas schicken, das das bild unter dem ausschnitt richtig hinschiebt ....
(Kopierschutz Monkey Island damals )
Also die GrabImage Variante ist mit GrabImage(#CanvasImage, #ImageAusschnitt, MouseX, MouseY, 40, 40) noch am sinnvollsten (von der Logik her)
Kein Ewiges erstellen und freigeben, sondern überschreiben.
P.S.
Wobei ich gerade die Idee hatte, anstelle eines ImageGadgets ein Canvas zu nehmen und dort einfach nur versetzt zu zeichnen. so wie z.B. Ein Grosses Bild liegt unter einem kleinen ausschnitt und wird bewegt...
Dann nur noch die Koordinaten berechnen und an das kleinere Canvas schicken, das das bild unter dem ausschnitt richtig hinschiebt ....
(Kopierschutz Monkey Island damals )
PureBasic 6.10 LTS (Windows x86/x64) | Windows10 Pro x64 | Asus TUF X570 Gaming Plus | R9 5900X | 64GB RAM | GeForce RTX 3080 TI iChill X4 | HAF XF Evo | build by vannicom
- man-in-black
- Beiträge: 362
- Registriert: 21.08.2006 17:39
Re: Ermitteln der Imagegröße eines CanvasGadgets?
Hi,
Da obiges bereits überlesen wurde, häng ich meinen Testcode einfach mal an :P
Vielleicht mag das ein W10 Nutzer mal ausführen. Würd mich auch interessieren.
MIB
Bisonte hat geschrieben:P.S.
Wobei ich gerade die Idee hatte, anstelle eines ImageGadgets ein Canvas zu nehmen und dort einfach nur versetzt zu zeichnen. so wie z.B. Ein Grosses Bild liegt unter einem kleinen ausschnitt und wird bewegt...
Dann nur noch die Koordinaten berechnen und an das kleinere Canvas schicken, das das bild unter dem ausschnitt richtig hinschiebt ....
(Kopierschutz Monkey Island damals )
zu spät :Pman-in-black hat geschrieben: kann dir da nicht groß helfen, aber wie wäre es mit einem zweiten Canvas, auf dem du das Bild einfach clipst?
Canvas1 ist dann das Original, zuständig für Hover ... und Canvas2 verschiebt sein dargestelltes Bild in einem 40x40 Viewport.
Ich hab folgendes einfach mal q&d mit Win7 ausgeführt. "Leider" gibts bei mir keinen Rahmen, weshalb ich da nichts weiter testen kann.man-in-black hat geschrieben:Und zu deinen Dimensionen. Hilft OutputHeight() vielleicht?
Da obiges bereits überlesen wurde, häng ich meinen Testcode einfach mal an :P
Vielleicht mag das ein W10 Nutzer mal ausführen. Würd mich auch interessieren.
Code: Alles auswählen
OpenWindow(#PB_Any,0,0,800,600,"")
CanvasGadget(1,0,0,800,600)
Repeat
event = WaitWindowEvent()
If event = #PB_Event_Gadget
Select EventGadget()
Case 1
If EventType() = #PB_EventType_LeftClick
Debug GadgetHeight(1)
Debug GadgetWidth(1)
StartDrawing(CanvasOutput(1))
Debug OutputHeight()
Debug OutputWidth()
DrawingMode(#PB_2DDrawing_Outlined)
Box(0,0,OutputWidth(),OutputHeight(),Random($FFFFFF)) ;visueller Test, ob Maße stimmen
StopDrawing()
Debug "-----"
EndIf
EndSelect
EndIf
Until event = #PB_Event_CloseWindow
Re: Ermitteln der Imagegröße eines CanvasGadgets?
Ok das hab ich wohl irgendwie wegen der Fachausdrücke nicht gerafft Man möge einem alten Mann verzeihen ....
Zu deinen Q&D TestCode auf Win 10... Rahmen beim Canvas gibts per #PB_Canvas_Border als Flag
Und die OutputWidth() + OutputHeight() Angaben sind tatsächlich auch mit Rahmen korrekt.
800x600 ohne Rahmen
796x596 mit Rahmen
Edit : Hier mal schnell zusammengeschusterst als beispiel beide Techniken... verschieben und überschreiben....
(halt entsprechend auskommentieren)
Wobei hier die Verschiebetechnik doch etwas mehr CPU Last erzeugt..
Es wird ja schliesslich noch das komplette Bild gezeichnet, auch wenn man es nicht sieht.
Zu deinen Q&D TestCode auf Win 10... Rahmen beim Canvas gibts per #PB_Canvas_Border als Flag
Und die OutputWidth() + OutputHeight() Angaben sind tatsächlich auch mit Rahmen korrekt.
800x600 ohne Rahmen
796x596 mit Rahmen
Edit : Hier mal schnell zusammengeschusterst als beispiel beide Techniken... verschieben und überschreiben....
(halt entsprechend auskommentieren)
Code: Alles auswählen
#BigImage = 1
#SmallImage = 2
Global mx, my
Procedure CanvasImage_Events()
If EventType() = #PB_EventType_MouseMove
mx = GetGadgetAttribute(EventGadget(), #PB_Canvas_MouseX)
my = GetGadgetAttribute(EventGadget(), #PB_Canvas_MouseY)
GrabImage(#BigImage, #SmallImage, mx, my, 40, 40) ; Die überschreibvariante
PostEvent(#PB_Event_Gadget, 0, 2, #PB_EventType_Change)
EndIf
EndProcedure
Procedure CanvasMini_Events()
If EventType() = #PB_EventType_Change
StartDrawing(CanvasOutput(2))
DrawImage(ImageID(#SmallImage), 0, 0) ; Die Überschreibvariante
; DrawImage(ImageID(#BigImage), -mx, -my) ; Die Verschiebetechnik
StopDrawing()
EndIf
EndProcedure
UsePNGImageDecoder()
LoadImage(#BigImage, "D:\Dein600x600px_Image.png")
OpenWindow(0, 0, 0, 800, 600, "Test", #PB_Window_ScreenCentered|#PB_Window_SystemMenu)
CanvasGadget(1, 0, 0, 600, 600, #PB_Canvas_Border)
StartDrawing(CanvasOutput(1))
DrawImage(ImageID(#BigImage), 0, 0)
StopDrawing()
CanvasGadget(2, 610, 0, 40, 40, #PB_Canvas_Border)
BindGadgetEvent(1,@CanvasImage_Events())
BindGadgetEvent(2,@CanvasMini_Events())
Repeat
Event = WaitWindowEvent()
If Event = #PB_Event_CloseWindow
Break
EndIf
ForEver
Es wird ja schliesslich noch das komplette Bild gezeichnet, auch wenn man es nicht sieht.
PureBasic 6.10 LTS (Windows x86/x64) | Windows10 Pro x64 | Asus TUF X570 Gaming Plus | R9 5900X | 64GB RAM | GeForce RTX 3080 TI iChill X4 | HAF XF Evo | build by vannicom
Re: Ermitteln der Imagegröße eines CanvasGadgets?
Moinsen,
besten Dank für Eure konstruktiven Beiträge. Ich werde es dann wohl mit festen Imagenummern realisieren.
Schade, dass diese Imagenummerierung von PureBasic (#PB_Any bzw. feste Werte, ImageID() usw.) so viel Spielraum für Missverständnisse bereit hält. Da hätte man sich vielleicht lieber auf ein einziges System geeinigt, z.B. alles nur mit Handles regeln, die dann auch das OS versteht.
besten Dank für Eure konstruktiven Beiträge. Ich werde es dann wohl mit festen Imagenummern realisieren.
Schade, dass diese Imagenummerierung von PureBasic (#PB_Any bzw. feste Werte, ImageID() usw.) so viel Spielraum für Missverständnisse bereit hält. Da hätte man sich vielleicht lieber auf ein einziges System geeinigt, z.B. alles nur mit Handles regeln, die dann auch das OS versteht.
"Never run a changing system!" | "Unterhalten sich zwei Alleinunterhalter... Paradox, oder?"
PB 6.02 x64, OS: Win 7 Pro x64 & Win 11 x64, Desktopscaling: 125%, CPU: I7 6500, RAM: 16 GB, GPU: Intel Graphics HD 520
Useralter in 2024: 56 Jahre.
PB 6.02 x64, OS: Win 7 Pro x64 & Win 11 x64, Desktopscaling: 125%, CPU: I7 6500, RAM: 16 GB, GPU: Intel Graphics HD 520
Useralter in 2024: 56 Jahre.