From 5720087dbe8c7498f11b0d61dc21b18cf519a204 Mon Sep 17 00:00:00 2001 From: Bartosz Firyn Date: Wed, 20 Mar 2013 11:07:46 +0100 Subject: [PATCH] Add image transformation feature, closes #73 --- .../example/ImageTransformerExample.java | 46 +++++ .../java/com/github/sarxos/webcam/Webcam.java | 169 +++++++++++------- .../sarxos/webcam/WebcamImageTransformer.java | 10 ++ .../github/sarxos/webcam/WebcamUpdater.java | 11 +- 4 files changed, 171 insertions(+), 65 deletions(-) create mode 100644 webcam-capture/src/example/java/com/github/sarxos/webcam/example/ImageTransformerExample.java create mode 100644 webcam-capture/src/main/java/com/github/sarxos/webcam/WebcamImageTransformer.java diff --git a/webcam-capture/src/example/java/com/github/sarxos/webcam/example/ImageTransformerExample.java b/webcam-capture/src/example/java/com/github/sarxos/webcam/example/ImageTransformerExample.java new file mode 100644 index 00000000..0846d6b9 --- /dev/null +++ b/webcam-capture/src/example/java/com/github/sarxos/webcam/example/ImageTransformerExample.java @@ -0,0 +1,46 @@ +package com.github.sarxos.webcam.example; + +import java.awt.image.BufferedImage; + +import javax.swing.JFrame; + +import com.github.sarxos.webcam.Webcam; +import com.github.sarxos.webcam.WebcamImageTransformer; +import com.github.sarxos.webcam.WebcamPanel; +import com.github.sarxos.webcam.WebcamResolution; +import com.github.sarxos.webcam.util.jh.JHGrayFilter; + + +public class ImageTransformerExample implements WebcamImageTransformer { + + private static final JHGrayFilter GRAY = new JHGrayFilter(); + + @Override + public BufferedImage transform(BufferedImage image) { + return GRAY.filter(image, null); + } + + public ImageTransformerExample() { + + Webcam webcam = Webcam.getDefault(); + webcam.setViewSize(WebcamResolution.VGA.getSize()); + webcam.setImageTransformer(this); + webcam.open(); + + JFrame window = new JFrame("Test Transformer"); + + WebcamPanel panel = new WebcamPanel(webcam); + panel.setFPSDisplayed(true); + panel.setFillArea(true); + + window.add(panel); + window.pack(); + window.setVisible(true); + window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + } + + public static void main(String[] args) { + new ImageTransformerExample(); + } + +} diff --git a/webcam-capture/src/main/java/com/github/sarxos/webcam/Webcam.java b/webcam-capture/src/main/java/com/github/sarxos/webcam/Webcam.java index 1aa18154..472a8186 100644 --- a/webcam-capture/src/main/java/com/github/sarxos/webcam/Webcam.java +++ b/webcam-capture/src/main/java/com/github/sarxos/webcam/Webcam.java @@ -117,6 +117,11 @@ public class Webcam { */ private WebcamUpdater updater = new WebcamUpdater(this); + /** + * IMage transformer. + */ + private volatile WebcamImageTransformer transformer = null; + /** * Webcam class. * @@ -262,6 +267,87 @@ public boolean close() { return true; } + /** + * Return underlying webcam device. Depending on the driver used to discover + * devices, this method can return instances of different class. By default + * {@link WebcamDefaultDevice} is returned when no external driver is used. + * + * @return Underlying webcam device instance + */ + public WebcamDevice getDevice() { + assert device != null; + return device; + } + + /** + * Completely dispose capture device. After this operation webcam cannot be + * used any more and full reinstantiation is required. + */ + protected void dispose() { + + assert disposed != null; + assert open != null; + assert driver != null; + assert device != null; + assert listeners != null; + + if (!disposed.compareAndSet(false, true)) { + return; + } + + open.set(false); + + LOG.info("Disposing webcam {}", getName()); + + WebcamDisposeTask task = new WebcamDisposeTask(driver, device); + try { + task.dispose(); + } catch (InterruptedException e) { + LOG.error("Processor has been interrupted before webcam was disposed!", e); + return; + } + + WebcamEvent we = new WebcamEvent(WebcamEventType.DISPOSED, this); + for (WebcamListener l : listeners) { + try { + l.webcamClosed(we); + l.webcamDisposed(we); + } catch (Exception e) { + LOG.error(String.format("Notify webcam disposed, exception when calling %s listener", l.getClass()), e); + } + } + + // hook can be null because there is a possibility that webcam has never + // been open and therefore hook was not created + if (hook != null) { + try { + Runtime.getRuntime().removeShutdownHook(hook); + } catch (IllegalStateException e) { + LOG.trace("Shutdown in progress, cannot remove hook"); + } + } + + LOG.debug("Webcam disposed {}", getName()); + } + + /** + * TRansform image using image transformer. If image transformer has not + * been set, this method return instance passed in the argument, without any + * modifications. + * + * @param image the image to be transformed + * @return Transformed image (if transformer is set) + */ + protected BufferedImage transform(BufferedImage image) { + if (image != null) { + WebcamImageTransformer tr = getImageTransformer(); + if (tr != null) { + return tr.transform(image); + } + } + return image; + } + /** * Is webcam open? * @@ -412,7 +498,7 @@ public BufferedImage getImage() { // get image t1 = System.currentTimeMillis(); - BufferedImage image = new WebcamReadImageTask(driver, device).getImage(); + BufferedImage image = transform(new WebcamReadImageTask(driver, device).getImage()); t2 = System.currentTimeMillis(); if (image == null) { @@ -822,69 +908,6 @@ public static void registerDriver(String clazzName) { DRIVERS_LIST.add(clazzName); } - /** - * Return underlying webcam device. Depending on the driver used to discover - * devices, this method can return instances of different class. By default - * {@link WebcamDefaultDevice} is returned when no external driver is used. - * - * @return Underlying webcam device instance - */ - public WebcamDevice getDevice() { - assert device != null; - return device; - } - - /** - * Completely dispose capture device. After this operation webcam cannot be - * used any more and full reinstantiation is required. - */ - protected void dispose() { - - assert disposed != null; - assert open != null; - assert driver != null; - assert device != null; - assert listeners != null; - - if (!disposed.compareAndSet(false, true)) { - return; - } - - open.set(false); - - LOG.info("Disposing webcam {}", getName()); - - WebcamDisposeTask task = new WebcamDisposeTask(driver, device); - try { - task.dispose(); - } catch (InterruptedException e) { - LOG.error("Processor has been interrupted before webcam was disposed!", e); - return; - } - - WebcamEvent we = new WebcamEvent(WebcamEventType.DISPOSED, this); - for (WebcamListener l : listeners) { - try { - l.webcamClosed(we); - l.webcamDisposed(we); - } catch (Exception e) { - LOG.error(String.format("Notify webcam disposed, exception when calling %s listener", l.getClass()), e); - } - } - - // hook can be null because there is a possibility that webcam has never - // been open and therefore hook was not created - if (hook != null) { - try { - Runtime.getRuntime().removeShutdownHook(hook); - } catch (IllegalStateException e) { - LOG.trace("Shutdown in progress, cannot remove hook"); - } - } - - LOG.debug("Webcam disposed {}", getName()); - } - /** * CAUTION!!!
*
@@ -979,4 +1002,22 @@ public static synchronized WebcamDiscoveryService getDiscoveryService() { } return discovery; } + + /** + * Return image transformer. + * + * @return Transformer instance + */ + public WebcamImageTransformer getImageTransformer() { + return transformer; + } + + /** + * Set image transformer. + * + * @param transformer the transformer to be set + */ + public void setImageTransformer(WebcamImageTransformer transformer) { + this.transformer = transformer; + } } diff --git a/webcam-capture/src/main/java/com/github/sarxos/webcam/WebcamImageTransformer.java b/webcam-capture/src/main/java/com/github/sarxos/webcam/WebcamImageTransformer.java new file mode 100644 index 00000000..9ea0d3ec --- /dev/null +++ b/webcam-capture/src/main/java/com/github/sarxos/webcam/WebcamImageTransformer.java @@ -0,0 +1,10 @@ +package com.github.sarxos.webcam; + +import java.awt.image.BufferedImage; + + +public interface WebcamImageTransformer { + + BufferedImage transform(BufferedImage image); + +} diff --git a/webcam-capture/src/main/java/com/github/sarxos/webcam/WebcamUpdater.java b/webcam-capture/src/main/java/com/github/sarxos/webcam/WebcamUpdater.java index fd71e0ba..079fa823 100644 --- a/webcam-capture/src/main/java/com/github/sarxos/webcam/WebcamUpdater.java +++ b/webcam-capture/src/main/java/com/github/sarxos/webcam/WebcamUpdater.java @@ -156,10 +156,19 @@ public void run() { // Calculate time required to fetch 1 picture. + WebcamDriver driver = Webcam.getDriver(); + WebcamDevice device = webcam.getDevice(); + + assert driver != null; + assert device != null; + + BufferedImage img = null; + t1 = System.currentTimeMillis(); - image.set(new WebcamReadImageTask(Webcam.getDriver(), webcam.getDevice()).getImage()); + img = webcam.transform(new WebcamReadImageTask(driver, device).getImage()); t2 = System.currentTimeMillis(); + image.set(img); imageNew = true; // Calculate delay required to achieve target FPS. In some cases it can