Seite 1 von 1

"Grundfarbe" aus einem Icon ermittlen

Verfasst: Mi, 15. Feb 2023 8:36
von ssemleit
Hallo,

ich suche eine Möglichkeit aus einem Icon die "Grundfarbe" oder "Durchschnittsfarbe" zu ermitteln.
Die Begriffe hab ich mir wohl gerade ausgedacht :D

Beispiel anhand 3 Icons:
icons.png
icons.png (2.86 KiB) 3320 mal betrachtet
Für das 1. Icon soll "grün", für das 2. Icon "gelb" und für das 3. Icon "blau" als RGB-Werte ermittelt werden.
Das möchte ich dazu nutzen, um in Dialogen bestimmte Bereiche in den Farben einfärben.

Gruß
Stefan

Re: "Grundfarbe" aus einem Icon ermittlen

Verfasst: Mi, 15. Feb 2023 9:01
von Tom
Mmh. Noch nie probiert, aber Du kannst aus den als XbpIcons geladenen Icons die XbpBitmap-Objekte erzeugen (:GetBitmap) und aus denen wiederum z.B. die Standard-Hintergrundfarbe mit ":getDefaultBGColor" auslesen. Ansonsten müsstest Du Bildpunkt für Bildpunkt die Farbe erheben, und die, die am häufigsten vorkommt, ist die gesuchte.

Re: "Grundfarbe" aus einem Icon ermittlen

Verfasst: Mi, 15. Feb 2023 9:08
von ssemleit
Ich habe auch schon daran gedacht, das Icon irgendwo hin zu pinseln und dann für alle Punkte (oder in einem Raster)
die einzelnen RGB Werte zu addieren (Hintergrundfarbe lass ich aus) und durch die Anzahl der "Messungen" zu teilen.
Nur hab ich nicht griffbereit, wie ich die Farbe eines Pixels ermitteln kann.

Re: "Grundfarbe" aus einem Icon ermittlen

Verfasst: Mi, 15. Feb 2023 9:51
von Tom
Die Pixel bestehen ja nur aus Farbe und sonst nichts - jeder Punkt ist Farbe. Irgendwo im Forum hat jemand (mit mehr als 90%iger Sicherheit würde ich vermuten: Jimmy) mal gezeigt, wie man Bitmaps pixelweise liest und auswertet.

Re: "Grundfarbe" aus einem Icon ermittlen

Verfasst: Mi, 15. Feb 2023 12:33
von AUGE_OHR
hi,

es gibt die API Function GetPixel()
https://learn.microsoft.com/en-us/windo ... i-getpixel

Code: Alles auswählen

DLLFUNCTION GetPixel( hDC, nX, nY ) USING STDCALL FROM GDI32.DLL

   oDlg:Static1:lbDown := {|aPos,uNIL,oSelf| oDlg:ShowColor(aPos)}

Code: Alles auswählen

METHOD DemoDlg:create( oParent, oOwner, aPos, aSize, aPP, lVisible )

   // hDC need for DLLcall
   ::hDC := ::Static1:winDevice():getHDC()

   // use :paint callback slot to repaint
   ::Static1:paint := {|aRect,uNIL,oSelf| ::StaticPaint() }

Code: Alles auswählen

METHOD DemoDlg:ShowColor(aPos)
LOCAL nColor := GetPixel(::hDC,aPos[1],aPos[2])
LOCAL aRGB   := GraGetRGBIntensity(AutomationTranslateColor(nColor,.T.))
   Msgbox("Color "+VAR2CHAR(aRGB),"Position "+VAR2CHAR(aPos) )
RETURN nil
p.s. bei 0,0 bekommt man die Farbe für "Transparency" also ab 1,1 die Farbe abfragen

Re: "Grundfarbe" aus einem Icon ermittlen

Verfasst: Mi, 15. Feb 2023 13:13
von Tom
Ja, aber GetPixel benötigt einen DeviceContext, also eine Drawingarea. Das geht (und man kann es automatisieren), wenn die Icons tatsächlich angezeigt werden, aber ist das auch, wonach Du suchst, Stefan?

Re: "Grundfarbe" aus einem Icon ermittlen

Verfasst: Mi, 15. Feb 2023 13:59
von ssemleit
So wie ich das verstehe, ist der Tipp von Jimmy sowas ähnliches wie ein ColorPicker, der eine Anzeige auf dem Bildschirm benötigt.
D.h. wenn das Element nicht sichtbar ist, kann ich auch nix von meinem Icon auslesen.
Da hab ich dann das Henne<>Ei Problem.

Ich habe ein XbpStatic und zeichne per Ownerdrawing mit XbpIcon:draw() das Icon und u.a. per GraBox() eine Box.
Die Box soll als Farbe die um einiges aufgehellte "Grundfarbe" des Icons haben.
Kunde.png
Kunde.png (2.53 KiB) 3259 mal betrachtet
Der Hintergrund soll anstelle des hellen blau hier ein helles grün werden.
Lieferant.png
Lieferant.png (2.46 KiB) 3259 mal betrachtet
Der Hintergrund soll anstelle des hellen blau hier ein helles gelbwerden.

Re: "Grundfarbe" aus einem Icon ermittlen

Verfasst: Mi, 15. Feb 2023 14:17
von Tom
Wenn Du die Koordinaten des Icons kennst (was der Fall sein dürfte - Du malst es ja per Ownerdrawing), kannst Du Jimmys Methode verwenden. Du zeichnest ja auf einen PS, und der liefert einen DeviceContext. Du musst nur das Icon abarbeiten, die verschiedenen Farben sammeln und die am häufigsten verwendete nutzen. Das dürfte auch ziemlich schnell gehen. Wenn Du das aber vor dem Zeichnen der Icons wissen willst, musst Du ein bisschen anders vorgehen.

Re: "Grundfarbe" aus einem Icon ermittlen

Verfasst: Mi, 15. Feb 2023 14:21
von ssemleit
Ich werde mal mein Glück versuchen.
Da ich jedoch erst die Box zeichne und darauf dann das Icon bin ich noch etwas skeptisch, ob ich damit Erfolg habe.
Weil für die Box brauch ich die Farbe vom Icon. Ich werde berichten...
Danke Tom und Jimmy.

Re: "Grundfarbe" aus einem Icon ermittlen

Verfasst: Mi, 15. Feb 2023 15:30
von AUGE_OHR
hi,

hast du links eine 2nd Monitor :?:

wenn Nein kannst du "negative" Koordinaten verwenden die man nicht "sehen" kann
wenn es "fertig" ist schiebst du es auf die richtige Position

---

man kann ein MemoryDC nutzen um alles im Speicher zu machen

Frage : arbeitest du mit Express++ :?:

ich "glaube" Roger hat mal ein Beispiel für Eugene mit Express++ gemacht
ich muss mal suchen wo das ist ...

---

Nachtrag : für den Device Context kann man auch das nehmen

Code: Alles auswählen

DLLFUNCTION GetWindowDC( hwnd ) USING STDCALL FROM USER32.DLL

   hDC1 := GetWindowDC( o:getHWnd() )

Re: "Grundfarbe" aus einem Icon ermittlen

Verfasst: Mi, 15. Feb 2023 15:38
von ssemleit
Hallo Jimmy,

ich habe mehrere Bildschirme. Je nach Kundeninstallation kann das durchaus auch vorkommen.
MemoryDC sagt mir leider nix.
Express++ verwende ich nicht.
Das Auslesen der RGB-Werte mittels Deiner Funktion ShowColor(aPos) klappt prima!

Gruß
Stefan

Re: "Grundfarbe" aus einem Icon ermittlen

Verfasst: Mi, 15. Feb 2023 15:41
von Tom
Hier:

http://bb.donnay-software.com/donnay/vi ... 364#p10364

Das basiert zwar auf eXpress++, aber die eigentlich verwendete Funktionalität ist unabhängig davon.

Re: "Grundfarbe" aus einem Icon ermittlen

Verfasst: Mi, 15. Feb 2023 15:49
von ssemleit
Danke Tom.
Dann versuch ich mal, Rogers Code auseinanderzunehmen und für mich zu verwenden.

Gruß
Stefan

Re: "Grundfarbe" aus einem Icon ermittlen

Verfasst: Do, 16. Feb 2023 9:55
von ssemleit
Also, die Grundfarbe ermitteln klappt jetzt ganz gut.
Das mit dem MemoryDC hab ich mir erst mal gespart und eine Krücke gebaut. Ich Pinsel erst das Icon und dann Hintergrund+Icon.
So sieht jeweils der Hintergrund mit der aus den Icons ermittelten Farbe aus:
kdli.png
kdli.png (5.64 KiB) 3614 mal betrachtet
Ich würde die Hintergrundfarben aber gerne etwas heller machen.
Hat jemand noch einen Tipp, wie ich aus den RGB-Werten "hellere" RGB-Werte bekomme?

Gruß
Stefan

Re: "Grundfarbe" aus einem Icon ermittlen

Verfasst: Do, 16. Feb 2023 12:49
von Marcus Herz

Code: Alles auswählen

/*============================================================================
 $Function:    TransformColor(nColor, nProz)
 $Group:			4
 $Author:      Marcus Herz
 $Topic:       RGB Farbwert aufhellen oder abdunkeln
 $Description:	Ein RGB Farbwert kann damit um einen Prozentfaktor aufgehellt oder abgedunkelt werden.
 $Argument:    nColor		RGB Farbwert, z.B. von GraMakeRGBColor()
 $Argument:    nProz			Prozentwert, kleiner 0 = aufhellen, größer 0 = abdunkeln
 $Return:      nRgbColor
 $See Also:
 $Example:
// helle Farbe als Hintergrund, abgedunkelte Farbe, wenn sich Cursor in der Zelle befindet
 oCol	:ColorBlock	:= {|x,oB,oC| {,GraMakeRGBColor({100,200,45}),,TransformColor(GraMakeRGBColor({100,200,45}),-10)}}

? TransformColor(GraMakeRGBColor({100,200,45}),-10)  // entspricht Farbwert {110,220,50}, aber ist heller
// volles rot, aufhellen
? TransformColor(GraMakeRGBColor({255,  0, 0 }), -10)  // entspricht Farbwert {255,26,26}, heller
? TransformColor(GraMakeRGBColor({255,  0, 0 }), -100)  // entspricht Farbwert {255,255,255}, weiss
==============================================================================*/
FUNC TransformColor(nColor, nProz)
	LOCAL nGreen, nBlue, nRed

	if band(nColor, 0x1000000 ) = 0																	// keine RGB Farbe
		RETURN nColor

	elseif nProz == 0
		RETURN nColor
	elseif nProz >= 100
      RETURN GraMakeRGBColor({0,0,0})
	elseif nProz <= -100
      RETURN GraMakeRGBColor({255,255,255})
	endif

	nRed		:= band(nColor, 0xFF)
	nGreen	:= band(nColor, 0xFF00)
	nBlue		:= band(nColor, 0xFF0000)

	nGreen	/= 2**8
	nBlue		/= 2**16
	nProz		*= -1                                                                   // vorzeichen umdrehen > 255,255,255 ist weiss

	if nRed == 0
		if nProz > 0
			nRed	:= 255 * nProz / 100
		endif
	else
		nRed		:= max(0, nRed + nRed * nProz / 100)
	endif
	if nGreen == 0
		if nProz > 0
			nGreen:= 255 * nProz / 100
		endif
	else
		nGreen	:= max(0, nGreen + nGreen * nProz / 100)
	endif
	if nBlue == 0
		if nProz > 0
			nBlue	:= 255 * nProz / 100
		endif
	else
		nBlue		:= max(0, nBlue + nBlue * nProz / 100)
	endif

	nColor	:= min(255, int(nRed))
	nColor	+= min(255, int(nGreen)) * 2**8
	nColor	+= min(255, int(nBlue)) * 2**16

	nColor	:= bor(nColor, 0x1000000)                                                // xbase bit setzen
RETURN nColor


Re: "Grundfarbe" aus einem Icon ermittlen

Verfasst: Do, 16. Feb 2023 13:27
von ssemleit
Hallo Marcus,

danke, die Funktion TransformColor() tut was es soll.

Gruß
Stefan