Torna indietro   Hardware Upgrade Forum > Software > Programmazione

AWS Summit Milano 2025: accelerare sull'IA per liberare il potenziale delle imprese italiane
AWS Summit Milano 2025: accelerare sull'IA per liberare il potenziale delle imprese italiane
Dal palco dell’AWS Summit Milano 2025 arriva un appello chiaro: accelerare sull’adozione dell’intelligenza artificiale. Tecnologie mature, casi d’uso concreti e nuove competenze al centro della trasformazione. Il cloud come abilitatore, tra infrastruttura, dati e sicurezza
Recensione HONOR Pad 10: a questo prezzo fa tremare la concorrenza
Recensione HONOR Pad 10: a questo prezzo fa tremare la concorrenza
HONOR Pad 10 è una fra le nuove proposte più convincenti nel mercato dei tablet Android, e offre al suo utente un display 2,5K da 12,1 pollici con frequenza di aggiornamento a 120Hz, design dalle dimensioni compatte e un ottimo processore. Il tutto mantenendo un prezzo accessibile che lo posiziona come alternativa credibile ai tablet premium del mercato, anche di Apple.
GIGABYTE RTX 5060 Ti EAGLE OC ICE alla prova: compatta ed essenziale
GIGABYTE RTX 5060 Ti EAGLE OC ICE alla prova: compatta ed essenziale
Gigabyte ha portato sul mercato la GeForce RTX 5060 Ti EAGLE OC ICE con 16 GB di memoria, scheda video polivalente per il gaming e anche per altri tipi di carichi, dalla produttività all'intelligenza artificiale. Punto di forza di questa proposta sono le dimensioni compatte, che la rendono ideale anche per configurazioni mini-ITX o simili.
Tutti gli articoli Tutte le news

Vai al Forum
Rispondi
 
Strumenti
Old 14-05-2009, 12:42   #1
*andre*
Senior Member
 
Iscritto dal: Sep 2007
Messaggi: 1071
[java] disegnare sopra Component (stream da webcam)

ciao ragazzi!

allora vi spiego il mio problema:
io sto usando jmf per ricavare uno stream video da una webcam, per poterlo visualizzare il player che realizzo mi ritorna un Component e io semplicemente lo appiccico a un JFrame e vedo lo stream, il mio problema è che con questa webcam io devo realizzare un multitouch e quindi ho bisogno di calibrare dei valori appena parte il programma, questi li metto a posto facendo toccare all'utente il pannello (messo sopra la web) in diverse regioni. per fare una interfaccia userfrendly vorrei poter disegnare SOPRA lo stream così che l'utente possa vedere dove toccare.

ora la mia domanda è come diavolo faccio?
se io ho il Component c0 (che sarebbe lo stream) non posso farmi passare il sio graphics e disegnare con quello, perchè mi dà errore, quindi come potrei fare?

grazie a quelli che ci hanno capito qualcosa
__________________
Affari: ariakasneverborne, PanCar, Luk@°°°, Fabio310, kintaro oe, krike, fabry180384, dariox am2, chiadoz, windsofchange, dado1979, Rudyduca, aleforumista, Sheva77
*andre* è offline   Rispondi citando il messaggio o parte di esso
Old 14-05-2009, 13:39   #2
PGI-Bis
Senior Member
 
L'Avatar di PGI-Bis
 
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
Se escludiamo il fatto che praticamente non mi ricordo più niente di specifico su JMF, la faccenda è semplicissima.

Prendi la webcam, apri il flusso video, lo disegni su un buffer (BufferedImage), copi quel buffer su un componente swing e ci disegni sopra o sotto, come preferisci.

Oppure, ancora più semplice, usi un Panel con un layout di tipo OverlayLayout. OverlayLayout consente di sovrapporre dei componenti. Sotto ci metti il Component del Player collegato alla webcam, sopra un Component personalizzato che, sovrascrivendo il metodo paint (siamo in AWT), disegna quel che vuoi sopra al flusso video.

Oppure puoi usare un FrameGrabber e un BufferToImage per ottenere degli "snapshot" della webcam da usare durante la calibrazione.

Insomma, hai un tot di alternative. Io proverei prima quella dell'OverlayLayout.
PGI-Bis è offline   Rispondi citando il messaggio o parte di esso
Old 14-05-2009, 14:02   #3
*andre*
Senior Member
 
Iscritto dal: Sep 2007
Messaggi: 1071
Quote:
Originariamente inviato da PGI-Bis Guarda i messaggi
Se escludiamo il fatto che praticamente non mi ricordo più niente di specifico su JMF, la faccenda è semplicissima.

Prendi la webcam, apri il flusso video, lo disegni su un buffer (BufferedImage), copi quel buffer su un componente swing e ci disegni sopra o sotto, come preferisci.

Oppure, ancora più semplice, usi un Panel con un layout di tipo OverlayLayout. OverlayLayout consente di sovrapporre dei componenti. Sotto ci metti il Component del Player collegato alla webcam, sopra un Component personalizzato che, sovrascrivendo il metodo paint (siamo in AWT), disegna quel che vuoi sopra al flusso video.

Oppure puoi usare un FrameGrabber e un BufferToImage per ottenere degli "snapshot" della webcam da usare durante la calibrazione.

Insomma, hai un tot di alternative. Io proverei prima quella dell'OverlayLayout.
grazie mille gentilissimo! provo subito

PS: che cosa bisogna utilizzare per creare un menu carino con animazioni? (simile a quello di windows surface per intenderci )
__________________
Affari: ariakasneverborne, PanCar, Luk@°°°, Fabio310, kintaro oe, krike, fabry180384, dariox am2, chiadoz, windsofchange, dado1979, Rudyduca, aleforumista, Sheva77
*andre* è offline   Rispondi citando il messaggio o parte di esso
Old 14-05-2009, 14:05   #4
PGI-Bis
Senior Member
 
L'Avatar di PGI-Bis
 
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
Bisogna inannzitutto saper disegnare. E questo è in genere l'ostacolo più grosso perchè un conto è la cosa magari caruccia che sa disegnare un programmatore e un conto è quell'interfaccia strafichissima che è in grado di disegnarti un grafico.

La realizzazione tecnica è poi solitamente super banale. javax.swing.Timer per animare le immagini disegnate su un qualsiasi componente o per realizzare le trasformazioni (traslazioni o rotazioni) dei componenti disegnati su un contenitore e il gioco è bell'e che finito.
PGI-Bis è offline   Rispondi citando il messaggio o parte di esso
Old 14-05-2009, 14:33   #5
*andre*
Senior Member
 
Iscritto dal: Sep 2007
Messaggi: 1071
mmm hai ragione sono i disegni che sono da sbav di solito

magari trovo qualcosa di già fatto

grazie mille per l'overlaylayout che funziona a meraviglia!!! ora lo implemento nel codice dello stream e ci lavoro un pò sopra
__________________
Affari: ariakasneverborne, PanCar, Luk@°°°, Fabio310, kintaro oe, krike, fabry180384, dariox am2, chiadoz, windsofchange, dado1979, Rudyduca, aleforumista, Sheva77
*andre* è offline   Rispondi citando il messaggio o parte di esso
Old 14-05-2009, 16:14   #6
*andre*
Senior Member
 
Iscritto dal: Sep 2007
Messaggi: 1071
mmmm l'overlaylayout se ne sbatte quando c'è lo stream (infatti funziona con due miei component), sarà perchè si aggiorna in continuazione.. caspita era ottima l'idea, altri gestori di layout che permettono uno z index?
__________________
Affari: ariakasneverborne, PanCar, Luk@°°°, Fabio310, kintaro oe, krike, fabry180384, dariox am2, chiadoz, windsofchange, dado1979, Rudyduca, aleforumista, Sheva77
*andre* è offline   Rispondi citando il messaggio o parte di esso
Old 14-05-2009, 16:42   #7
PGI-Bis
Senior Member
 
L'Avatar di PGI-Bis
 
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
direi che il componente del player si fa beffe dell'ordine z.

Opzione B. FrameGrabber e BufferToImage, poi disegni l'immagine su un component (in questo caso puoi usare anche componenti Swing).
PGI-Bis è offline   Rispondi citando il messaggio o parte di esso
Old 14-05-2009, 16:59   #8
*andre*
Senior Member
 
Iscritto dal: Sep 2007
Messaggi: 1071
Quote:
Originariamente inviato da PGI-Bis Guarda i messaggi
direi che il componente del player si fa beffe dell'ordine z.

Opzione B. FrameGrabber e BufferToImage, poi disegni l'immagine su un component (in questo caso puoi usare anche componenti Swing).
consigliabile perchè sono più leggeri?
quale sarebbe il componente più "base" e leggero di swing per far disegnare un'img?
dovrebbe essere JComponent che estende direttamente gli awt container e component.. mi sbaglio?

perchè a me non serve che mi metta a disposizione un sacco di cose, basta che abbia il metodo paint da sovrascrivere (per disegnare la mia griglia) e possa disegnare in'immagine, devo stare attento alle prestazioni purtroppo
__________________
Affari: ariakasneverborne, PanCar, Luk@°°°, Fabio310, kintaro oe, krike, fabry180384, dariox am2, chiadoz, windsofchange, dado1979, Rudyduca, aleforumista, Sheva77
*andre* è offline   Rispondi citando il messaggio o parte di esso
Old 14-05-2009, 17:07   #9
PGI-Bis
Senior Member
 
L'Avatar di PGI-Bis
 
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
puoi usare anche un component awt. Con l'uso di framegrabber comunque perdi qualcosa in prestazioni. Bisogna vedere se le performace risultanti restano nell'alveo delle aspettative.
PGI-Bis è offline   Rispondi citando il messaggio o parte di esso
Old 14-05-2009, 17:27   #10
*andre*
Senior Member
 
Iscritto dal: Sep 2007
Messaggi: 1071
ok ci provo vediamo cosa viene fuori

ma visto che ne sai, c'è un tool o qualcosa che mi faccia da benchmark?

uso eclipse come ide, e mi servirebbe un riscontro reale(non solo teorico) se un algoritmo è + o - veloce di un altro...
__________________
Affari: ariakasneverborne, PanCar, Luk@°°°, Fabio310, kintaro oe, krike, fabry180384, dariox am2, chiadoz, windsofchange, dado1979, Rudyduca, aleforumista, Sheva77
*andre* è offline   Rispondi citando il messaggio o parte di esso
Old 14-05-2009, 17:50   #11
PGI-Bis
Senior Member
 
L'Avatar di PGI-Bis
 
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
Diciamo che l'impatto dovrebbe essere sufficientemente evidente da poter essere rilevato tramite un profiler (cioè noterai un incremento delle operazioni di gestione della memoria in termini di allocazione-deallocazioni della young generation e un uso più intenso del processore).

Un profiler tipo jvisualvm è in grado di dirti anche il tempo medio di esecuzione di un singolo metodo. Una comparazione tra il prima e il dopo dovrebbe quindi quantificare il peggioramento di performance.
PGI-Bis è offline   Rispondi citando il messaggio o parte di esso
Old 14-05-2009, 19:36   #12
*andre*
Senior Member
 
Iscritto dal: Sep 2007
Messaggi: 1071
ok grazie!!
lo proverò domani, intanto funziona il metodo di grabbare il frame e spararlo su un Component, operazione che tra l'altro dovevo fare comunque visto che li devo analizzare uno ad uno, quindi ne creo solo una copia e non perdo neanche molto in prestazioni
__________________
Affari: ariakasneverborne, PanCar, Luk@°°°, Fabio310, kintaro oe, krike, fabry180384, dariox am2, chiadoz, windsofchange, dado1979, Rudyduca, aleforumista, Sheva77
*andre* è offline   Rispondi citando il messaggio o parte di esso
Old 15-05-2009, 16:56   #13
*andre*
Senior Member
 
Iscritto dal: Sep 2007
Messaggi: 1071
caspita non riesco a farlo funzionare con eclipse, va beh non importa..

senza aprire un altro 3d ti volevo chiedere gentilmente se mi potresti spiegare come funziona il doppio buffering?
così non ho problemi di "refresh"
__________________
Affari: ariakasneverborne, PanCar, Luk@°°°, Fabio310, kintaro oe, krike, fabry180384, dariox am2, chiadoz, windsofchange, dado1979, Rudyduca, aleforumista, Sheva77
*andre* è offline   Rispondi citando il messaggio o parte di esso
Old 15-05-2009, 17:46   #14
PGI-Bis
Senior Member
 
L'Avatar di PGI-Bis
 
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
Il principe del double buffering in Java è BufferStrategy.

Molto semplicemente si tratta di scavalcare in toto il meccanismo di rendering dei componenti AWT e andare a operare direttamente sui buffer hardware. Puoi specificare il numero di superfici da allocare (generalmente due) e lasciare che Java 2D si occupi di sostituire i buffer.

Si prende un java.awt.Canvas (o un java.awt.Frame).
Appena questo diventa visibile si crea un BufferStrategy invocando il suo metodo createBufferStrategy.
A questo punto si avvia un ciclo di rendering la cui esecuzione è affidata all'Event Dispatcher (ad esempio tramite un javax.swing.Timer) e ciclicamente si recupera il BufferStrategy del canvas (getBufferStrategy), si disegna sul contesto grafico del buffer corrente (getDrawGraphics()) e si sostituiscono i buffer (bufferStrategy.show()).

Un esempio potrebbe essere questo:

Codice:
import java.awt.*;
import java.awt.image.*;
import javax.swing.*;
import java.awt.event.*;

public class Main {

	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				new Main().start();
			}
		});
	}
	
	private void start() {
		/* Esempio di operazione di disegno da passare a screen. */
		final PaintCallback paint = new PaintCallback() {
			public void draw(Graphics2D g, int width, int height) {
				g.setPaint(Color.BLACK);
				g.fillRect(0, 0, width, height);
				g.setPaint(Color.WHITE);
				g.drawString("hello world", width / 3, height / 2);
				
			}
		};
		
		
		final Frame window = new Frame("DoubleBuffer test");
		final Screen screen = new Screen(paint);
		window.setLayout(new GridLayout(1, 1));
		window.add(screen);
		
		window.addWindowListener(new WindowAdapter() {
			
			/** Avvia il ciclo di rendering di screen quando la finestra viene
			proiettata sullo schermo. */
			public void windowOpened(WindowEvent e) {
				screen.start();
			}
			
			/** Ferma il ciclo di rendering e chiude la finestra, terminando
			il programma se non ci sono altre finestre visibili o altri
			Thread non demoni in esecuzione. */
			public void windowClosing(WindowEvent e) {
				screen.stop();
				window.dispose();
			}
		});
		window.setSize(640, 480);
		window.setVisible(true);
	}
}

/** Dichiarazione di un'operazione di disegno su un contesto grafico. */
interface PaintCallback {
	public void draw(Graphics2D g, int screenWidth, int screenHeight);
}

/** Usiamo un Canvas per via del possesso da parte di questo componente di
un BufferStrategy autonomo. */
class Screen extends Canvas {
	
	/* invocazione della funzione di rendering, impacchettata in un
	ActionListener per poterlo passare ad un javax.swing.Timer. */
	private final ActionListener DO_RENDERING_CALL = new ActionListener() {
		public void actionPerformed(ActionEvent e) {
			doRendering();
		}
	};
	
	/* Pausa tra un'invocazione e la successiva di doRendering. Necessaria per
	evitare che l'Event Dispatcher Thread ritardi l'esecuzione delle operazioni
	di input */
	private final int RENDERING_LOOP_DELAY_MS = 10;
	
	/* Un javax.swing.Timer esegue ciclicamente il metodo actionPerformed
	dell'actionListener nell'Event Dispatcher Thread */
	private final javax.swing.Timer RENDERER = new javax.swing.Timer(
		RENDERING_LOOP_DELAY_MS, DO_RENDERING_CALL);
		
	/* numero di buffer da allocare per le operazioni di rendering. */
	private final int BUFFER_COUNT = 2;
	
	/* operazione di disegno eseguita dal ciclo di rendering, definita
	esternamente a Screen (per comodità) */
	private final PaintCallback PAINT_CALLBACK;
	
	/** Inizializza uno screen. Lo Screen esegue ciclicamente il metodo
	draw di paintCallback. PaintCallback non può essere null. */
	public Screen(PaintCallback paintCallback) {
		if(paintCallback == null) {
			throw new IllegalArgumentException("paint callback cannot be null");
		}
		PAINT_CALLBACK = paintCallback;
	}
	
	/** Questo metodo viene invocato dall'AWT quando questo componente diviene
	parte di un albero di componenti visibili. A partire da questo momento
	è possibile richiedere la creazione di un BufferStrategy. */
	@Override public void addNotify() {
		super.addNotify();
		createBufferStrategy(BUFFER_COUNT);
	}
	
	/** Avvia il ciclo di rendering. */
	public void start() {
		RENDERER.start();
	}
	
	/** Ferma il ciclo di rendering. */
	public void stop() {
		RENDERER.stop();
	}
	
	/** Esegue l'operazione di disegno definita in PAINT_CALLBACK usando il
	buffer corrente di BufferStrategy. */
	private void doRendering() {
		BufferStrategy bs = getBufferStrategy();
		if(bs != null) {
			do {
				do {
					int height = getHeight();
					Graphics2D g = (Graphics2D)bs.getDrawGraphics();
					PAINT_CALLBACK.draw(g, getWidth(), getHeight());
					g.dispose();
				} while(bs.contentsRestored());
				bs.show();
			} while(bs.contentsLost());
		}
	}
}
Questa è la seconda tecnica di rendering di basso livello più performante che puoi ottenere dalle librerie standard. La prima prevede l'uso di un Frame al posto di canvas ma è per il resto identica.
PGI-Bis è offline   Rispondi citando il messaggio o parte di esso
Old 17-05-2009, 14:35   #15
*andre*
Senior Member
 
Iscritto dal: Sep 2007
Messaggi: 1071
grazie sempre gentilissimo!
lo implementerò di sicuro tanto è semplice e utile

ora devo creare gli eventi per il touch, sarà un bel casino.. anche perchè dovrò gestire tutto io..

già che sono qui ti chiedo un parere su come farlo, ecco la mia idea:
semplificando io avrò un thred che costantemente monitora il touch e rileva i movimenti, quando i rilevamenti saranno compatibili con un evento (move click, etc) lancerò il metodo di un oggetto (che implementerà una mia interfaccia così non ho problemi con la firma dei metodi stessi e i paramentri), registrato precedentemente, corrispondente all'evento che ho rilevato. e a me basterà inserire il codice che voglio venga eseguito in corrispondenza di un move dentro la classe che implementa la mia interfaccia e che registrerò come handler di default.

che ne pensi?
__________________
Affari: ariakasneverborne, PanCar, Luk@°°°, Fabio310, kintaro oe, krike, fabry180384, dariox am2, chiadoz, windsofchange, dado1979, Rudyduca, aleforumista, Sheva77
*andre* è offline   Rispondi citando il messaggio o parte di esso
Old 17-05-2009, 14:47   #16
PGI-Bis
Senior Member
 
L'Avatar di PGI-Bis
 
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
Considerando che è possibile accodare eventi nella coda degli eventi di sistema e che questo accodamento genera una propagazione degli eventi a tutti i componenti awt/swing secondo il meccanismo predefinito io opterei per la creazione di un producer che converta i dati delle rilevazioni tramite webcam in eventi AWT.

Così facendo oltre a poter creare il tuo programma avresti la possibilità di usare un qualsiasi altro programma java dotato di interfaccia grafica già creato.

Probabilmente c'è da riflettere sulla traduzione in eventi AWT di un interazione multipla con periferiche della stessa classe (il multitouch è come avere N mouse attivi ognuno dei quali genera eventi distinguibili). Penso che potrebbe essere gestito con un ID o meglio ancora delle sottoclassi di MouseEvent.

Questo è più meno quello che mi viene in mente.
PGI-Bis è offline   Rispondi citando il messaggio o parte di esso
Old 17-05-2009, 16:17   #17
*andre*
Senior Member
 
Iscritto dal: Sep 2007
Messaggi: 1071
Quote:
Originariamente inviato da PGI-Bis Guarda i messaggi
Considerando che è possibile accodare eventi nella coda degli eventi di sistema e che questo accodamento genera una propagazione degli eventi a tutti i componenti awt/swing secondo il meccanismo predefinito io opterei per la creazione di un producer che converta i dati delle rilevazioni tramite webcam in eventi AWT.

Così facendo oltre a poter creare il tuo programma avresti la possibilità di usare un qualsiasi altro programma java dotato di interfaccia grafica già creato.

Probabilmente c'è da riflettere sulla traduzione in eventi AWT di un interazione multipla con periferiche della stessa classe (il multitouch è come avere N mouse attivi ognuno dei quali genera eventi distinguibili). Penso che potrebbe essere gestito con un ID o meglio ancora delle sottoclassi di MouseEvent.

Questo è più meno quello che mi viene in mente.
ottima idea, ma non riesco a capire come si possa implementare
__________________
Affari: ariakasneverborne, PanCar, Luk@°°°, Fabio310, kintaro oe, krike, fabry180384, dariox am2, chiadoz, windsofchange, dado1979, Rudyduca, aleforumista, Sheva77
*andre* è offline   Rispondi citando il messaggio o parte di esso
Old 27-05-2009, 16:13   #18
Alexander_br
Junior Member
 
Iscritto dal: May 2009
Messaggi: 3
Salve ragazzi..ho letto quanto scritto e avrei un problema attinente alla discussione..
Sono riuscito a prende l'input da una webcam e attaccarlo su JPanel in java, fin qui nessun problema. Ora vorrei poter fare una sorta di touch come diceva andre, però non ho idea di come fare per prendere il movimento della mano. Ho visto su internet che molti giocano cn i colori e si fanno una sorta di track con la mano però non so come fare..Consigli? Grazie mille in anticipo..
Alexander_br è offline   Rispondi citando il messaggio o parte di esso
 Rispondi


AWS Summit Milano 2025: accelerare sull'IA per liberare il potenziale delle imprese italiane AWS Summit Milano 2025: accelerare sull'IA per l...
Recensione HONOR Pad 10: a questo prezzo fa tremare la concorrenza Recensione HONOR Pad 10: a questo prezzo fa trem...
GIGABYTE RTX 5060 Ti EAGLE OC ICE alla prova: compatta ed essenziale GIGABYTE RTX 5060 Ti EAGLE OC ICE alla prova: co...
AMD Ryzen Threadripper 9000 e Radeon AI Pro R9700, per le workstation AI AMD Ryzen Threadripper 9000 e Radeon AI Pro R970...
Nuova Ford Capri elettrica, la super prova: in viaggio, in città e in autostrada Nuova Ford Capri elettrica, la super prova: in v...
VMware Cloud Foundation 9.0: il private ...
Roscosmos ha lanciato uno o più s...
Scopri Project Indigo: l’app gratuita di...
Sky Wifi Business: la fibra ultraveloce ...
SpaceX Starship: questa la possibile cau...
Open Innovation: al via la challenge di ...
FSR 4 di AMD funziona anche sulle schede...
C'è solo un modo per comprare Nin...
Spotify Music Pro in arrivo: audio hi-fi...
Questo costosissimo dissipatore AIO ha p...
Le offerte più toste di Amazon, t...
Starlink Mini: antenna e router gratis c...
Pubblicità su WhatsApp? Per l'UE ...
Samsung Galaxy S25 Ultra 512 GB e 1 TB i...
Tre prodotti per rendere l'ingresso di c...
Chromium
GPU-Z
OCCT
LibreOffice Portable
Opera One Portable
Opera One 106
CCleaner Portable
CCleaner Standard
Cpu-Z
Driver NVIDIA GeForce 546.65 WHQL
SmartFTP
Trillian
Google Chrome Portable
Google Chrome 120
VirtualBox
Tutti gli articoli Tutte le news Tutti i download

Strumenti

Regole
Non Puoi aprire nuove discussioni
Non Puoi rispondere ai messaggi
Non Puoi allegare file
Non Puoi modificare i tuoi messaggi

Il codice vB è On
Le Faccine sono On
Il codice [IMG] è On
Il codice HTML è Off
Vai al Forum


Tutti gli orari sono GMT +1. Ora sono le: 15:28.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Served by www2v