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