From b388a5decf5957cbb119b8c020baef200760d6e1 Mon Sep 17 00:00:00 2001
From: ulrich
Date: Fri, 11 Feb 2022 13:03:59 +0000
Subject: [PATCH] Bildbetrachter hinzugefuegt
---
src/de/uhilger/calypso/Betrachter.java | 143 ++++++++++++++++++++
src/org/tw/pi/framebuffer/FrameBuffer.java | 236 +++++++++++++++++++++++++++++++++
2 files changed, 379 insertions(+), 0 deletions(-)
diff --git a/src/de/uhilger/calypso/Betrachter.java b/src/de/uhilger/calypso/Betrachter.java
new file mode 100644
index 0000000..3890072
--- /dev/null
+++ b/src/de/uhilger/calypso/Betrachter.java
@@ -0,0 +1,143 @@
+package de.uhilger.calypso;
+
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+import java.net.URL;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.imageio.ImageIO;
+import org.tw.pi.framebuffer.FrameBuffer;
+
+/**
+ * Klasse zum Betrachten von Fotografien auf dem Fernseher
+ * mit dem Raspberry Pi
+ *
+ * Diese Klasse verwendet die Klasse JavaFrameBuffer
+ * von Thomas Welsch, die die Ausgabe direkt in den
+ * FrameBuffer des Raspberry Pi erlaubt.
+ *
+ * Der JavaFrameBuffer ist mit Calypso
+ * enthalten und erfordert, dass beim Start die native
+ * Programmbibliothek namens 'libFrameBuffer.so' eingebunden wird, die im Verteilpaket
+ * von Calypso enthalten ist. Zum Einbinden der nativen Biliothek genuegt die
+ * Angabe von -Djava.library.path=/pfad/zum/lib-ordner im Startskript von
+ * Calypso.
+ *
+ * Durch die Verwendung des Framebuffer kann das Betrachten von
+ * Bildern auf dem Fernseher erfolgen ohne, dass auf dem Raspberry Pi
+ * eine grafische Bedienoberflaeche wie z.B. das X Windowing System,
+ * XBMC oder OpenELEC, usw. laufen muss. Es genuegt Java
+ * im 'headless mode', was zudem die Bedienbarkeit aus der Ferne via
+ * HTTP hinzufuegt.
+ *
+ * @author Ulrich Hilger, https://uhilger.de
+ * @author Published under the terms and conditions of
+ * the <a href="http://www.gnu.org/licenses/agpl-3.0" target="_blank">GNU Affero General Public License</a>
+ *
+ * @version 2 vom 11. Februar 2022, Version 1 war vom 15.1.2014
+ */
+public class Betrachter {
+
+ public static final long serialVersionUID = 42L;
+
+ private static final Logger logger = Logger.getLogger(Betrachter.class.getName());
+
+ public static final String P_FBDEV = "fbdev";
+ public static final String STANDARD_FBDEV = "/dev/fb0";
+
+ public static final String P_URL = "u";
+ public static final String P_X = "x";
+ public static final String P_Y = "y";
+ public static final String P_WIDTH = "w";
+ public static final String P_HEIGHT = "h";
+
+ //public static final String PATH_ZEIGEN = "/zeigen";
+ //public static final String PATH_LOESCHEN = "/loeschen";
+
+ private FrameBuffer jfb;
+ private BufferedImage img;
+ private Graphics2D g;
+
+ public void init(String devName) {
+ String device = devName;
+ if(device == null) {
+ device = STANDARD_FBDEV;
+ }
+ jfb = new FrameBuffer(device, false);
+ img = jfb.getScreen();
+ g = img.createGraphics();
+ }
+
+ public void close() {
+ jfb.close();
+ }
+
+ public void jfbHelloWorld() {
+ g.setColor(Color.RED);
+ g.drawString("Hello World !", 50, 50);
+ jfb.updateScreen();
+ }
+
+ /**
+ * Anzeigen eines Bildes mit Hilfe des JavaFrameBuffers
+ *
+ * Diese Methode laedt ein Bild via HTTP oder HTTPS und
+ * schreibt es in den Framebuffer zur Anzeige
+ *
+ * @param urlStr Adresse des Bildes, das angezeigt werden soll
+ * @param x waagerechte Koordinate der gewuenschten Position der linken oberen Ecke des Bildes
+ * @param y senkrechte Koordinate der gewuenschten Position der linken oberen Ecke des Bildes
+ * @param w Breite in Bildpunkten, in der das Bild angezeigt werden soll
+ * @param h Hoehe in Bildpunkten, in der das Bild angezeigt werden soll
+ */
+ public String jfbBildZeigen(String urlStr, int x, int y, int w, int h) {
+ String antwort = "jfbBildZeigen hat nicht geklappt";
+ BufferedImage webimg = null;
+ try {
+ /*
+ vgl. http://java.kompf.de/java2d.html
+ */
+ //System.setProperty("sun.java2d.opengl","true");
+ URL url = new URL(urlStr);
+ webimg = ImageIO.read(url);
+ g.drawImage(webimg, x, y, w, h, null);
+ jfb.updateScreen();
+ antwort = urlStr + " geladen";
+ } catch (Exception e) {
+ antwort = e.getMessage();
+ }
+ return antwort;
+ }
+
+ /**
+ * Leeren des FrameBuffers
+ *
+ * Hier wird einfach ein Linux-Prozess eroeffnet, der das
+ * Kommando dd if=/dev/zero of=/dev/fb0 ausfuehrt und
+ * den Framebuffer mit Nullwerten fuellt
+ */
+ public String fbLeeren(String deviceName) {
+ String antwort = "fbLeeren hat nicht geklappt";
+ try {
+ String cmd = "dd if=/dev/zero of=" + deviceName;
+ Process leeren = Runtime.getRuntime().exec(cmd);
+ /*MeldeThread t = new MeldeThread();
+ t.setProcess(leeren);
+ t.lauscherHinzufuegen(new ProzessLauscherImpl() {
+ @Override
+ public void prozessBeendet() {
+ // etwas tun, wenn fertig...
+ }
+ });
+ t.start();*/
+ antwort = "Prozess gestartet";
+ } catch(Exception ex) {
+ logger.log(Level.FINE, ex.getMessage(), ex);
+ }
+ return antwort;
+ }
+
+
+
+}
diff --git a/src/org/tw/pi/framebuffer/FrameBuffer.java b/src/org/tw/pi/framebuffer/FrameBuffer.java
new file mode 100644
index 0000000..45afda2
--- /dev/null
+++ b/src/org/tw/pi/framebuffer/FrameBuffer.java
@@ -0,0 +1,236 @@
+package org.tw.pi.framebuffer;
+
+/*
+* This file is the JNI Java part of a Raspberry Pi FrameBuffer project.
+*
+* Created 2013 by Thomas Welsch (ttww@gmx.de).
+*
+* Do whatever you want to do with it :-)
+*
+**/
+
+
+
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.image.BufferedImage;
+import java.awt.image.DataBufferInt;
+
+import javax.swing.JPanel;
+
+
+/**
+* This class is the Java front end for a simple to use FrameBuffer driver.
+* Simple draw in the BufferedImage and all changes are transfered to the FrameBuffer device.<p>
+* For testing purpose a dummy device is supported (via the devicename "dummy_160x128" instead of "/dev/fb1").<p<
+* The Java process needs write access to the frame buffer device file.
+* <p>
+* It's used to drive small bit mapped screens connected via SPI, see
+* http://www.sainsmart.com/blog/ada/
+* <p>
+* <p>
+* My Linux kernel config for SPI display was:
+* <pre>
+* CONFIG_FB_ST7735=y
+* CONFIG_FB_ST7735_PANEL_TYPE_RED_TAB=y
+* CONFIG_FB_ST7735_RGB_ORDER_REVERSED=y
+* CONFIG_FB_ST7735_MAP=y
+* CONFIG_FB_ST7735_MAP_RST_GPIO=25
+* CONFIG_FB_ST7735_MAP_DC_GPIO=24
+* CONFIG_FB_ST7735_MAP_SPI_BUS_NUM=0
+* CONFIG_FB_ST7735_MAP_SPI_BUS_CS=0
+* CONFIG_FB_ST7735_MAP_SPI_BUS_SPEED=16000000
+* CONFIG_FB_ST7735_MAP_SPI_BUS_MODE=0
+* </pre>
+* CONFIG_FB_ST7735_MAP_SPI_BUS_SPEED gives faster updates :-)
+* <p>
+* If you get the wrong colors, try the CONFIG_FB_ST7735_RGB_ORDER_REVERSED option !
+*/
+public class FrameBuffer {
+
+ private static final int FPS = 60; // Max. update rate
+
+ private String deviceName;
+
+ private long deviceInfo; // Private data from JNI C
+
+ private int width,height;
+ private int bits;
+
+ private BufferedImage img;
+ private int[] imgBuffer;
+
+ // -----------------------------------------------------------------------------------------------------------------
+
+ private native long openDevice(String device);
+ private native void closeDevice(long di);
+ private native int getDeviceWidth(long di);
+ private native int getDeviceHeight(long di);
+ private native int getDeviceBitsPerPixel(long di);
+ private native boolean updateDeviceBuffer(long di,int[] buffer);
+
+ static {
+ System.loadLibrary("FrameBufferJNI"); // FrameBufferJNI.dll (Windows) or FrameBufferJNI.so (Unixes)
+ }
+
+ // -----------------------------------------------------------------------------------------------------------------
+
+ /**
+ * Open the named frame buffer device and starts the automatic update thread between the internal
+ * BufferedImage and the device.
+ *
+ * @param deviceName e.g. /dev/fb1 or dummy_320x200
+ */
+ public FrameBuffer(String deviceName) {
+ this(deviceName,true);
+ }
+
+ // -----------------------------------------------------------------------------------------------------------------
+
+ /**
+ * Open the named frame buffer device.
+ *
+ * @param deviceName e.g. /dev/fb1 or dummy_320x200
+ * @param autoUpdate if true, starts the automatic update thread between the internal
+ * BufferedImage and the device.
+ */
+ public FrameBuffer(String deviceName, boolean autoUpdate) {
+
+ this.deviceName = deviceName;
+
+ deviceInfo = openDevice(deviceName);
+
+ if (deviceInfo < 10) {
+ throw new IllegalArgumentException("Init. for frame buffer "+deviceName+" failed with error code "+deviceInfo);
+ }
+
+ this.width = getDeviceWidth(deviceInfo);
+ this.height = getDeviceHeight(deviceInfo);
+
+ System.err.println("Open with "+deviceName+" ("+deviceInfo+")");
+ System.err.println(" width "+getDeviceWidth(deviceInfo));
+ System.err.println(" height "+getDeviceHeight(deviceInfo));
+ System.err.println(" bpp "+getDeviceBitsPerPixel(deviceInfo));
+
+ // We always use ARGB image type.
+ img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
+ imgBuffer = ((DataBufferInt) img.getRaster().getDataBuffer()).getBankData()[0];
+
+ if (autoUpdate) new UpdateThread().start();
+ }
+
+ // -----------------------------------------------------------------------------------------------------------------
+
+ private ScreenPanel screenPanel;
+
+ /**
+ * Returns a JPanel which represents the actual frame buffer device.
+ *
+ * @return JPanel...
+ */
+ public JPanel getScreenPanel() {
+ synchronized (deviceName) {
+ if (screenPanel != null) throw new IllegalStateException("Only one screen panel supported");
+
+ screenPanel = new ScreenPanel();
+
+ return screenPanel;
+ }
+ }
+
+ // -----------------------------------------------------------------------------------------------------------------
+
+ /**
+ * Internal helper class for displaying the current frame buffer image via a JPanel.
+ */
+ @SuppressWarnings("serial")
+ private class ScreenPanel extends JPanel {
+ public ScreenPanel() {
+ setPreferredSize(new Dimension(FrameBuffer.this.width,FrameBuffer.this.height));
+ }
+
+ @Override
+ protected void paintComponent(Graphics g) {
+ super.paintComponent(g);
+ g.drawImage(img, 0, 0, null);
+ }
+ }
+
+ // -----------------------------------------------------------------------------------------------------------------
+
+ /**
+ * Internal helper class for refreshing the frame buffer display and/or JPanel.
+ */
+ private class UpdateThread extends Thread {
+
+ UpdateThread() {
+ setDaemon(true);
+ setName("FB "+deviceName+ " update");
+ }
+
+ @Override
+ public void run() {
+ final int SLEEP_TIME = 1000 / FPS;
+
+ while (deviceInfo != 0) {
+
+ if (updateScreen()) {
+ if (screenPanel != null) {
+ screenPanel.repaint();
+ }
+ }
+
+ try {
+ sleep(SLEEP_TIME);
+ } catch (InterruptedException e) {
+ break;
+ }
+
+ } // while
+
+ }
+
+ } // class UpdateThread
+
+ // -----------------------------------------------------------------------------------------------------------------
+
+ /**
+ * Returns the BufferedImage for drawing. Anything your draw here is synchronizet to the frame buffer.
+ *
+ * @return BufferedImage of type ARGB.
+ */
+ public BufferedImage getScreen() {
+ return img;
+ }
+
+ // -----------------------------------------------------------------------------------------------------------------
+
+ /**
+ * Close the device.
+ */
+ public void close() {
+ synchronized (deviceName) {
+ closeDevice(deviceInfo);
+ deviceInfo = 0;
+ img = null;
+ imgBuffer = null;
+ }
+ }
+
+ // -----------------------------------------------------------------------------------------------------------------
+
+ /**
+ * Update the screen if no automatic sync is used (see constructor autoUpdate flag).
+ * This method is normally called by the autoUpdate thread.
+ *
+ * @return true if the BufferedImage was changed since the last call.
+ */
+ public boolean updateScreen() {
+ synchronized (deviceName) {
+ if (deviceInfo == 0) return false;
+ return updateDeviceBuffer(deviceInfo,imgBuffer);
+ }
+ }
+
+
+} // of class
\ No newline at end of file
--
Gitblit v1.9.3