Ottenere il valore di un pixel in una DrawingArea

Da Gambas-it.org - Wikipedia.

Per ottenere il valore di un pixel in una DrawingArea, terremo conto che essa è comunque una finestra.

Usare le risorse della Classe "DesktopWidow"

Questa modalità prevede che passando alla Classe "DesktopWidow" del Componente "gb.desktop.x11" il numero identificativo della finestra dell'Oggetto DrawingArea, sarà possibile ottenere la schermata della sola DrawingArea, quindi conseguentemente un Oggetto "Image"ed infine individuare il pixel del punto cliccato con il mouse.

Private DrawingArea1 As DrawingArea


Public Sub Form_Open()

 With Me
   .W = Screen.AvailableWidth * 0.3
   .H = Screen.AvailableHeight * 0.3
   .Center
 End With
 With DrawingArea1 = New DrawingArea(Me) As "DrawingArea1"
   .X = 0
   .Y = 0
   .W = Me.W
   .H = Me.H * 0.5
 End With

End

Public Sub DrawingArea1_Draw()

 Dim c As Integer[] = [Color.Blue, Color.Green, Color.Yellow, Color.Red]
 Dim ff As Float[] = [0, 0.34, 0.67, 1]

' Disegna all'interno della "DrawingArea":
 With Paint
   .Brush = .LinearGradient(0, 0, DrawingArea1.W, DrawingArea1.H, c, ff)
   .Rectangle(0, 0, DrawingArea1.W, DrawingArea1.H)
   .Fill
  .End
 End With

End

Public Sub DrawingArea1_MouseUp()

 Dim dw As DesktopWindow
 
 With dw = New DesktopWindow(DrawingArea1.Handle)
   Print Hex(.GetScreenshot(True).Image[Mouse.X, Mouse.Y], 6)
 End With

End


Usare le risorse della Classe "Desktop"

Questa modalità, utilizzando il Metodo ".Screenshot()" della Classe "Desktop" del Componente "gb.desktop", sarà possibile ottenere la schermata della sola DrawingArea, quindi conseguentemente un Oggetto "Image"ed infine individuare il pixel del punto cliccato con il mouse.

Private DrawingArea1 As DrawingArea


Public Sub Form_Open()

 With Me
   .W = Screen.AvailableWidth * 0.3
   .H = Screen.AvailableHeight * 0.3
   .Center
 End With
 With DrawingArea1 = New DrawingArea(Me) As "DrawingArea1"
   .X = 0
   .Y = 0
   .W = Me.W
   .H = Me.H * 0.5
 End With

End

Public Sub DrawingArea1_Draw()

 Dim c As Integer[] = [Color.Blue, Color.Green, Color.Yellow, Color.Red]
 Dim ff As Float[] = [0, 0.34, 0.67, 1]

' Disegna all'interno della "DrawingArea":
 With Paint
   .Brush = .LinearGradient(0, 0, DrawingArea1.W, DrawingArea1.H, c, ff)
   .Rectangle(0, 0, DrawingArea1.W, DrawingArea1.H)
   .Fill
  .End
 End With

End

Public Sub DrawingArea1_MouseUp()

 Dim im As Image

 im = Desktop.Screenshot(DrawingArea1.ScreenX, DrawingArea1.ScreenY, DrawingArea1.W, DrawingArea1.H).Image
 
 Print Hex(im[Mouse.X, Mouse.Y], 6)

End


Usando le funzioni esterne del API di X11

Per ottenere il valore di un pixel presente in una DrawingArea, è possibile anche utilizzare alcune funzioni esterne della libreria di X11. Ciò è possibile, in quanto la DrawingArea non è nient'altro che una finestra come le altre, avente un proprio numero identificativo, sulla quale si potrà agire con la predetta libreria di X11.

Sarà necessario richiamare nell'applicativo Gambas la libreria di X attualmente: "libX11.so.6.3.0 ".

Mostriamo di seguito un breve codice, nel quale disegneremo all'interno di una DrawingArea una riga colorata con tutta la gamma dei colori dal blu al rosso. Individueremo il valore pixel, facente parte di tale riga colorata della DrawingArea, sul quale si sarà cliccato con il puntatore del mouse, e ne mostreremo in console il valore in rappresentazione esadecimale:

Library "libX11:6.3.0"

Private Enum XYBitmap = 0, XYPixmap, ZPixmap

' Display *XOpenDisplay(char *display_name)
' Opens a connection to the X server that controls a display.
Private Extern XOpenDisplay(display_name As Pointer) As Pointer

' unsigned long XAllPlanes()
' Returns a value with all bits set to 1 suitable for use in a plane argument to a procedure.
Private Extern XAllPlanes() As Long

' XImage *XGetImage(Display *display, Drawable d, int x, int y, unsigned int width, unsigned int height, unsigned long plane_mask, int format)
' Returns a pointer to an XImage structure.
Private Extern XGetImage(displayP As Pointer, d As Long, xI As Integer, yI As Integer, wid As Integer, hei As Integer, plane_mask As Long, formatI As Integer) As Pointer

' unsigned long XGetPixel(XImage *ximage, int x, int y)
' Returns the specified pixel from the named image.
Private Extern XGetPixel(ximage As Pointer, xI As Integer, yI As Integer) As Long

' XCloseDisplay(Display *display)
' Closes the connection to the X server for the display specified in the Display structure and destroys all windows.
Private Extern XCloseDisplay(displayP As Pointer)


Public Sub Form_Open()
  
 DrawingArea1.Background = Color.White

End

Public Sub DrawingArea1_Draw()
  
 Dim c As Integer[] = [Color.Blue, Color.Green, Color.Yellow, Color.Red]
 Dim ff As Float[] = [0, 0.34, 0.67, 1]
 
' Disegnamo all'interno della "DrawingArea":
 With Paint
   .Brush = .LinearGradient(10, 40, 300, 40, c, ff)
   .Rectangle(10, 40, 300, 40)
   .Fill
   .End
 End With
 
End

Public Sub DrawingArea1_MouseUp()

 Dim dsp, XImage As Pointer
 
 dsp = XOpenDisplay(0)
 If dsp == 0 Then Error.Raise("Impossibile aprire una connessione al server X !")
   
' Otteniamo un puntatore alla "Struttura" contenente i dati dell'immagine disegnata nella "DrawingArea":
 XImage = XGetImage(dsp, DrawingArea1.Handle, 0, 0, DrawingArea1.W, DrawingArea1.H, XAllPlanes(), XYPixmap)
 If XImage == 0 Then Error.Raise("Impossibile ottenere un 'Puntatore' ai dati dell'immagine della DrawingArea !")
 
' Mostriamo il valore in esadecimale di un pixel posto alle coordinate individuate cliccando sulla riga colorata
' con il puntatore del mouse e passate alla seguente funzione esterna mediante il 2° e il 3° parametro:
 Print Hex(XGetPixel(XImage, Mouse.X, Mouse.Y), 8)
 
' Va in chiusura:
 XCloseDisplay(dsp)

End


Riferimenti

- http://www.x.org/wiki
- http://tronche.com/gui/x/xlib/