Download Jar. Uses 6490K of libraries. Click here for Pure Java version (10470L/73K).
!7 import static java.awt.RenderingHints.KEY_ANTIALIASING; import static java.awt.RenderingHints.KEY_INTERPOLATION; import static java.awt.RenderingHints.KEY_RENDERING; import static java.awt.RenderingHints.VALUE_ANTIALIAS_OFF; import static java.awt.RenderingHints.VALUE_ANTIALIAS_ON; import static java.awt.RenderingHints.VALUE_INTERPOLATION_BILINEAR; import static java.awt.RenderingHints.VALUE_RENDER_SPEED; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import org.slf4j.Logger; import org.slf4j.LoggerFactory; static BufferedImage imageFromWebcamPanel(WebcamPanel2 panel) { ret panel.image; } /** * Simply implementation of JPanel allowing users to render pictures taken with webcam. * * @author Bartosz Firyn (SarXos) */ sclass WebcamPanel2 extends JPanel implements WebcamListener, PropertyChangeListener { /** * This enum is to control of how image will be drawn in the panel bounds. * * @author Sylwia Kauczor */ public enum DrawMode { /** * Do not resize image - paint it as it is. This will make the image to go off out the * bounds if panel is smaller than image size. */ NONE, /** * Will resize image to the panel bounds. This mode does not care of the image scale, so the * final image may be disrupted. */ FILL, /** * Will fir image into the panel bounds. This will resize the image and keep both x and y * scale factor. */ FIT, } public interface ImageSupplier { public BufferedImage get(); } private static class DefaultImageSupplier implements ImageSupplier { private final Webcam webcam; public DefaultImageSupplier(Webcam webcam) { this.webcam = webcam; } @Override public BufferedImage get() { return webcam.getImage(); } } /** * Interface of the painter used to draw image in panel. * * @author Bartosz Firyn (SarXos) */ public interface Painter { /** * Paint panel without image. * * @param panel the webcam panel to paint on * @param g2 the graphics 2D object used for drawing */ void paintPanel(WebcamPanel2 panel, Graphics2D g2); /** * Paint webcam image in panel. * * @param panel the webcam panel to paint on * @param image the image from webcam * @param g2 the graphics 2D object used for drawing */ void paintImage(WebcamPanel2 panel, BufferedImage image, Graphics2D g2); } /** * Default painter used to draw image in panel. * * @author Bartosz Firyn (SarXos) * @author Sylwia Kauczor */ public class DefaultPainter implements Painter { /** * Webcam device name. */ private String name = null; /** * Lat repaint time, uset for debug purpose. */ private long lastRepaintTime = -1; /** * Buffered image resized to fit into panel drawing area. */ private BufferedImage resizedImage = null; @Override public void paintPanel(WebcamPanel2 owner, Graphics2D g2) { assert owner != null; assert g2 != null; Object antialiasing = g2.getRenderingHint(KEY_ANTIALIASING); g2.setRenderingHint(KEY_ANTIALIASING, isAntialiasingEnabled() ? VALUE_ANTIALIAS_ON : VALUE_ANTIALIAS_OFF); g2.setBackground(Color.BLACK); g2.fillRect(0, 0, getWidth(), getHeight()); int cx = (getWidth() - 70) / 2; int cy = (getHeight() - 40) / 2; g2.setStroke(new BasicStroke(2)); g2.setColor(Color.LIGHT_GRAY); g2.fillRoundRect(cx, cy, 70, 40, 10, 10); g2.setColor(Color.WHITE); g2.fillOval(cx + 5, cy + 5, 30, 30); g2.setColor(Color.LIGHT_GRAY); g2.fillOval(cx + 10, cy + 10, 20, 20); g2.setColor(Color.WHITE); g2.fillOval(cx + 12, cy + 12, 16, 16); g2.fillRoundRect(cx + 50, cy + 5, 15, 10, 5, 5); g2.fillRect(cx + 63, cy + 25, 7, 2); g2.fillRect(cx + 63, cy + 28, 7, 2); g2.fillRect(cx + 63, cy + 31, 7, 2); g2.setColor(Color.DARK_GRAY); g2.setStroke(new BasicStroke(3)); g2.drawLine(0, 0, getWidth(), getHeight()); g2.drawLine(0, getHeight(), getWidth(), 0); String str; final String strInitDevice = rb.getString("INITIALIZING_DEVICE"); final String strNoImage = rb.getString("NO_IMAGE"); final String strDeviceError = rb.getString("DEVICE_ERROR"); if (errored) { str = strDeviceError; } else { str = starting ? strInitDevice : strNoImage; } FontMetrics metrics = g2.getFontMetrics(getFont()); int w = metrics.stringWidth(str); int h = metrics.getHeight(); int x = (getWidth() - w) / 2; int y = cy - h; g2.setFont(getFont()); g2.setColor(Color.WHITE); g2.drawString(str, x, y); if (name == null) { name = webcam.getName(); } str = name; w = metrics.stringWidth(str); h = metrics.getHeight(); g2.drawString(str, (getWidth() - w) / 2, cy - 2 * h); g2.setRenderingHint(KEY_ANTIALIASING, antialiasing); } @Override public void paintImage(WebcamPanel2 owner, BufferedImage image, Graphics2D g2) { assert owner != null; assert image != null; assert g2 != null; int pw = getWidth(); int ph = getHeight(); int iw = image.getWidth(); int ih = image.getHeight(); Object antialiasing = g2.getRenderingHint(KEY_ANTIALIASING); Object rendering = g2.getRenderingHint(KEY_RENDERING); g2.setRenderingHint(KEY_ANTIALIASING, VALUE_ANTIALIAS_OFF); g2.setRenderingHint(KEY_RENDERING, VALUE_RENDER_SPEED); g2.setBackground(Color.BLACK); g2.setColor(Color.BLACK); g2.fillRect(0, 0, pw, ph); // resized image position and size int x = 0; int y = 0; int w = 0; int h = 0; switch (drawMode) { case NONE: w = image.getWidth(); h = image.getHeight(); break; case FILL: w = pw; h = ph; break; case FIT: double s = Math.max((double) iw / pw, (double) ih / ph); double niw = iw / s; double nih = ih / s; double dx = (pw - niw) / 2; double dy = (ph - nih) / 2; w = (int) niw; h = (int) nih; x = (int) dx; y = (int) dy; break; } if (resizedImage != null) { resizedImage.flush(); } if (w == image.getWidth() && h == image.getHeight() && !mirrored) { resizedImage = image; } else { GraphicsEnvironment genv = GraphicsEnvironment.getLocalGraphicsEnvironment(); GraphicsConfiguration gc = genv.getDefaultScreenDevice().getDefaultConfiguration(); Graphics2D gr = null; try { resizedImage = gc.createCompatibleImage(pw, ph); gr = resizedImage.createGraphics(); gr.setComposite(AlphaComposite.Src); for (Map.Entry<RenderingHints.Key, Object> hint : imageRenderingHints.entrySet()) { gr.setRenderingHint(hint.getKey(), hint.getValue()); } gr.setBackground(Color.BLACK); gr.setColor(Color.BLACK); gr.fillRect(0, 0, pw, ph); int sx1, sx2, sy1, sy2; // source rectangle coordinates int dx1, dx2, dy1, dy2; // destination rectangle coordinates dx1 = x; dy1 = y; dx2 = x + w; dy2 = y + h; if (mirrored) { sx1 = iw; sy1 = 0; sx2 = 0; sy2 = ih; } else { sx1 = 0; sy1 = 0; sx2 = iw; sy2 = ih; } gr.drawImage(image, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, null); } finally { if (gr != null) { gr.dispose(); } } } g2.drawImage(resizedImage, 0, 0, null); if (isFPSDisplayed()) { String str = String.format("FPS: %.1f", webcam.getFPS()); int sx = 5; int sy = ph - 5; g2.setFont(getFont()); g2.setColor(Color.BLACK); g2.drawString(str, sx + 1, sy + 1); g2.setColor(Color.WHITE); g2.drawString(str, sx, sy); } if (isImageSizeDisplayed()) { String res = String.format("%d\u2A2F%d px", iw, ih); FontMetrics metrics = g2.getFontMetrics(getFont()); int sw = metrics.stringWidth(res); int sx = pw - sw - 5; int sy = ph - 5; g2.setFont(getFont()); g2.setColor(Color.BLACK); g2.drawString(res, sx + 1, sy + 1); g2.setColor(Color.WHITE); g2.drawString(res, sx, sy); } if (isDisplayDebugInfo()) { if (lastRepaintTime < 0) { lastRepaintTime = System.currentTimeMillis(); } else { long now = System.currentTimeMillis(); String res = String.format("DEBUG: repaints per second: %.1f", (double) 1000 / (now - lastRepaintTime)); lastRepaintTime = now; g2.setFont(getFont()); g2.setColor(Color.BLACK); g2.drawString(res, 6, 16); g2.setColor(Color.WHITE); g2.drawString(res, 5, 15); } } g2.setRenderingHint(KEY_ANTIALIASING, antialiasing); g2.setRenderingHint(KEY_RENDERING, rendering); } } private static final class PanelThreadFactory implements ThreadFactory { private static final AtomicInteger number = new AtomicInteger(0); @Override public Thread newThread(Runnable r) { Thread t = new Thread(r, String.format("webcam-panel-scheduled-executor-%d", number.incrementAndGet())); t.setUncaughtExceptionHandler(WebcamExceptionHandler.getInstance()); t.setDaemon(true); return t; } } /** * This runnable will do nothing more than repaint panel. */ private static final class SwingRepainter implements Runnable { private WebcamPanel2 panel = null; public SwingRepainter(WebcamPanel2 panel) { this.panel = panel; } @Override public void run() { panel.repaint(); } } private static final long serialVersionUID = 1L; private static final Logger LOG = LoggerFactory.getLogger(WebcamPanel2.class); public static final double MIN_FREQUENCY = 0.016; // 1 frame per minute private static final double MAX_FREQUENCY = 50; // 50 frames per second private static final ThreadFactory THREAD_FACTORY = new PanelThreadFactory(); public static final Map<RenderingHints.Key, Object> DEFAULT_IMAGE_RENDERING_HINTS = new HashMap<RenderingHints.Key, Object>(); static { DEFAULT_IMAGE_RENDERING_HINTS.put(KEY_INTERPOLATION, VALUE_INTERPOLATION_BILINEAR); DEFAULT_IMAGE_RENDERING_HINTS.put(KEY_RENDERING, VALUE_RENDER_SPEED); DEFAULT_IMAGE_RENDERING_HINTS.put(KEY_ANTIALIASING, VALUE_ANTIALIAS_ON); } /** * This runnable will do nothing more than repaint panel. */ private final Runnable repaint = new SwingRepainter(this); /** * Rendering hints to be used when painting image to be displayed. */ private Map<RenderingHints.Key, Object> imageRenderingHints = new HashMap<RenderingHints.Key, Object>(DEFAULT_IMAGE_RENDERING_HINTS); /** * Scheduled executor acting as timer. */ private ScheduledExecutorService executor = null; /** * Image updater reads images from camera and force panel to be repainted. * * @author Bartosz Firyn (SarXos) */ private class ImageUpdater implements Runnable { private class RepaintScheduler extends Thread { public RepaintScheduler() { setUncaughtExceptionHandler(WebcamExceptionHandler.getInstance()); setName(String.format("repaint-scheduler-%s", webcam.getName())); setDaemon(true); } @Override public void run() { // do nothing when not running if (!running.get() || isInIconifiedFrame(WebcamPanel2.this)) { _sleep(100); return; } repaintPanel(); // loop when starting, to wait for images while (starting) { try { Thread.sleep(50); } catch (InterruptedException e) { throw new RuntimeException(e); } } // schedule update when webcam is open, otherwise schedule // second scheduler execution try { // FPS limit means that panel rendering frequency is // limited to the specific value and panel will not be // rendered more often then specific value if (webcam.isOpen()) { // TODO: rename FPS value in panel to rendering // frequency if (isFPSLimited()) { executor.scheduleAtFixedRate(updater, 0, (long) (1000 / frequency), TimeUnit.MILLISECONDS); } else { executor.scheduleWithFixedDelay(updater, 100, 1, TimeUnit.MILLISECONDS); } } else { executor.schedule(this, 500, TimeUnit.MILLISECONDS); } } catch (RejectedExecutionException e) { // executor has been shut down, which means that someone // stopped panel / webcam device before it was actually // completely started (it was in "starting" timeframe) LOG.warn("Executor rejected paint update"); LOG.trace("Executor rejected paint update because of", e); } } } /** * Update scheduler thread. */ private Thread scheduler = null; /** * Is repainter running? */ private AtomicBoolean running = new AtomicBoolean(false); /** * Start repainter. Can be invoked many times, but only first call will take effect. */ public void start() { if (running.compareAndSet(false, true)) { executor = Executors.newScheduledThreadPool(1, THREAD_FACTORY); scheduler = new RepaintScheduler(); scheduler.start(); } } /** * Stop repainter. Can be invoked many times, but only first call will take effect. * * @throws InterruptedException */ public void stop() throws InterruptedException { if (running.compareAndSet(true, false)) { executor.shutdown(); executor.awaitTermination(5000, TimeUnit.MILLISECONDS); scheduler.join(); } } @Override public void run() { try { update(); } catch (Throwable t) { errored = true; WebcamExceptionHandler.handle(t); } } /** * Perform single panel area update (repaint newly obtained image). */ private void update() { // do nothing when updater not running, when webcam is closed, or // panel repainting is paused if (!running.get() || !webcam.isOpen() || paused) { return; } // get new image from webcam BufferedImage tmp = supplier.get(); boolean repaint = true; if (tmp != null) { // ignore repaint if image is the same as before if (image == tmp) { repaint = false; } errored = false; image = tmp; } if (repaint) { repaintPanel(); } } } /** * Resource bundle. */ private ResourceBundle rb = null; /** * The mode of how the image will be resized to fit into panel bounds. Default is * {@link DrawMode#FIT} * * @see DrawMode */ private DrawMode drawMode = DrawMode.FIT; /** * Frames requesting frequency. */ private double frequency = 5; // FPS /** * Is frames requesting frequency limited? If true, images will be fetched in configured time * intervals. If false, images will be fetched as fast as camera can serve them. */ private boolean frequencyLimit = false; /** * Display FPS. */ private boolean frequencyDisplayed = false; /** * Display image size. */ private boolean imageSizeDisplayed = false; /** * Is antialiasing enabled (true by default). */ private boolean antialiasingEnabled = true; /** * Webcam object used to fetch images. */ private final Webcam webcam; private final ImageSupplier supplier; /** * Repainter is used to fetch images from camera and force panel repaint when image is ready. */ private final ImageUpdater updater; /** * Image currently being displayed. */ BufferedImage image = null; /** * Webcam is currently starting. */ private volatile boolean starting = false; /** * Painting is paused. */ private volatile boolean paused = false; /** * Is there any problem with webcam? */ private volatile boolean errored = false; /** * Webcam has been started. */ private final AtomicBoolean started = new AtomicBoolean(false); /** * Default painter. */ private final Painter defaultPainter = new DefaultPainter(); /** * Painter used to draw image in panel. * * @see #setPainter(Painter) * @see #getPainter() */ private Painter painter = defaultPainter; /** * Preferred panel size. */ private Dimension defaultSize = null; /** * If debug info should be displayed. */ private boolean displayDebugInfo = false; /** * Is image mirrored. */ private boolean mirrored = false; /** * Creates webcam panel and automatically start webcam. * * @param webcam the webcam to be used to fetch images */ public WebcamPanel2(Webcam webcam) { this(webcam, true); } /** * Creates new webcam panel which display image from camera in you your Swing application. * * @param webcam the webcam to be used to fetch images * @param start true if webcam shall be automatically started */ public WebcamPanel2(Webcam webcam, boolean start) { this(webcam, null, start); } /** * Creates new webcam panel which display image from camera in you your Swing application. If * panel size argument is null, then image size will be used. If you would like to fill panel * area with image even if its size is different, then you can use * {@link WebcamPanel#setFillArea(boolean)} method to configure this. * * @param webcam the webcam to be used to fetch images * @param size the size of panel * @param start true if webcam shall be automatically started * @see WebcamPanel#setFillArea(boolean) */ public WebcamPanel2(Webcam webcam, Dimension size, boolean start) { this(webcam, size, start, new DefaultImageSupplier(webcam)); } public WebcamPanel2(Webcam webcam, Dimension size, boolean start, ImageSupplier supplier) { if (webcam == null) { throw new IllegalArgumentException(String.format("Webcam argument in %s constructor cannot be null!", getClass().getSimpleName())); } this.defaultSize = size; this.webcam = webcam; this.updater = new ImageUpdater(); this.supplier = supplier; this.rb = WebcamUtils.loadRB(WebcamPanel.class, getLocale()); setDoubleBuffered(true); addPropertyChangeListener("locale", this); if (size == null) { Dimension r = webcam.getViewSize(); if (r == null) { r = webcam.getViewSizes()[0]; } setPreferredSize(r); } else { setPreferredSize(size); } if (start) { start(); } } /** * Set new painter. Painter is a class which pains image visible when * * @param painter the painter object to be set */ public void setPainter(Painter painter) { this.painter = painter; } /** * Get painter used to draw image in webcam panel. * * @return Painter object */ public Painter getPainter() { return painter; } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); if (image == null) { painter.paintPanel(this, (Graphics2D) g); } else { painter.paintImage(this, image, (Graphics2D) g); } } /** * Open webcam and start rendering. */ public void start() { if (!started.compareAndSet(false, true)) { return; } webcam.addWebcamListener(this); LOG.debug("Starting panel rendering and trying to open attached webcam"); updater.start(); starting = true; final SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() { @Override protected Void doInBackground() throws Exception { try { if (!webcam.isOpen()) { errored = !webcam.open(); } } catch (WebcamException e) { errored = true; throw e; } finally { starting = false; repaintPanel(); } return null; } }; worker.execute(); } /** * Stop rendering and close webcam. */ public void stop() { if (!started.compareAndSet(true, false)) { return; } webcam.removeWebcamListener(this); LOG.debug("Stopping panel rendering and closing attached webcam"); try { updater.stop(); } catch (InterruptedException e) { throw new RuntimeException(e); } image = null; final SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() { @Override protected Void doInBackground() throws Exception { try { if (webcam.isOpen()) { errored = !webcam.close(); } } catch (WebcamException e) { errored = true; throw e; } finally { repaintPanel(); } return null; } }; worker.execute(); } /** * Repaint panel in Swing asynchronous manner. */ private void repaintPanel() { SwingUtilities.invokeLater(repaint); } /** * Pause rendering. */ public void pause() { if (paused) { return; } LOG.debug("Pausing panel rendering"); paused = true; } /** * Resume rendering. */ public void resume() { if (!paused) { return; } LOG.debug("Resuming panel rendering"); paused = false; } /** * Is frequency limit enabled? * * @return True or false */ public boolean isFPSLimited() { return frequencyLimit; } /** * Enable or disable frequency limit. Frequency limit should be used for <b>all IP cameras * working in pull mode</b> (to save number of HTTP requests). If true, images will be fetched * in configured time intervals. If false, images will be fetched as fast as camera can serve * them. * * @param frequencyLimit true if limiting the frequency of image requests */ public void setFPSLimited(boolean frequencyLimit) { this.frequencyLimit = frequencyLimit; } /** * Get rendering frequency in FPS (equivalent to Hz). * * @return Rendering frequency */ public double getFPSLimit() { return frequency; } /** * Set rendering frequency (in Hz or FPS). Minimum frequency is 0.016 (1 frame per minute) and * maximum is 25 (25 frames per second). * * @param fps the frequency */ public void setFPSLimit(double fps) { if (fps > MAX_FREQUENCY) { fps = MAX_FREQUENCY; } if (fps < MIN_FREQUENCY) { fps = MIN_FREQUENCY; } this.frequency = fps; } /** * Is displaying of some debug information enabled. * * @return True if debug information are enabled, false otherwise */ public boolean isDisplayDebugInfo() { return displayDebugInfo; } /** * Display some debug information on image surface. * * @param displayDebugInfo the value to control debug information */ public void setDisplayDebugInfo(boolean displayDebugInfo) { this.displayDebugInfo = displayDebugInfo; } /** * This method return true in case if camera FPS is set to be displayed on panel surface. * Default value returned is false. * * @return True if camera FPS is set to be displayed on panel surface * @see #setFPSDisplayed(boolean) */ public boolean isFPSDisplayed() { return frequencyDisplayed; } /** * This method is to control if camera FPS should be displayed on the webcam panel surface. * * @param displayed the value to control if camera FPS should be displayed */ public void setFPSDisplayed(boolean displayed) { this.frequencyDisplayed = displayed; } /** * This method will return true in case when panel is configured to display image size. The * string will be printed in the right bottom corner of the panel surface. * * @return True in case if panel is configured to display image size */ public boolean isImageSizeDisplayed() { return imageSizeDisplayed; } /** * Configure panel to display camera image size to be displayed. * * @param imageSizeDisplayed if true the pixel dimensions are displayed over the image. */ public void setImageSizeDisplayed(boolean imageSizeDisplayed) { this.imageSizeDisplayed = imageSizeDisplayed; } /** * Turn on/off antialiasing. * * @param antialiasing the true to enable, false to disable antialiasing */ public void setAntialiasingEnabled(boolean antialiasing) { this.antialiasingEnabled = antialiasing; } /** * @return True is antialiasing is enabled, false otherwise */ public boolean isAntialiasingEnabled() { return antialiasingEnabled; } /** * Is webcam panel repainting starting. * * @return True if panel is starting */ public boolean isStarting() { return starting; } /** * Is webcam panel repainting started. * * @return True if panel repainting has been started */ public boolean isStarted() { return started.get(); } /** * This method returns the current draw mode, mainly used by custom painters * * @return the current value of the {@link DrawMode} */ public DrawMode getDrawMode() { return this.drawMode; } /** * This method sets the drawmode * * @param drawMode the desired {@link DrawMode} */ public void setDrawMode(DrawMode drawMode) { this.drawMode = drawMode; } /** * Indicates whether the panel is in an error state * * @return true if the panel has an error present */ public boolean isErrored() { return errored; } /** * Hints for rendering, mainly used for custom painters * * @return the stored RenderingHints * @deprecated use {@link #getDrawMode()} instead. */ @Deprecated public Map<RenderingHints.Key, Object> getImageRenderingHints() { return imageRenderingHints; } @Deprecated public boolean isFitArea() { return drawMode == DrawMode.FIT; } /** * This method will change the mode of panel area painting so the image will be resized and will * keep scale factor to fit into drawable panel bounds. When set to false, the mode will be * reset to {@link DrawMode#NONE} so image will be drawn as it is. * * @param fitArea the fit area mode enabled or disabled * @deprecated use {@link #setDrawMode(DrawMode drawMode)} instead. */ @Deprecated public void setFitArea(boolean fitArea) { this.drawMode = fitArea ? DrawMode.FIT : DrawMode.NONE; } /** * Image will be resized to fill panel area if true. If false then image will be rendered as it * was obtained from webcam instance. * * @param fillArea shall image be resided to fill panel area * @deprecated use {@link #setDrawMode(DrawMode drawMode)} instead. */ @Deprecated public void setFillArea(boolean fillArea) { this.drawMode = fillArea ? DrawMode.FILL : DrawMode.NONE; } /** * Get value of fill area setting. Image will be resized to fill panel area if true. If false * then image will be rendered as it was obtained from webcam instance. * * @return True if image is being resized, false otherwise * @deprecated use {@link #getDrawMode()} instead. */ @Deprecated public boolean isFillArea() { return drawMode == DrawMode.FILL; } /** * Get default painter used to draw panel. * * @return Default painter */ public Painter getDefaultPainter() { return defaultPainter; } @Override public void propertyChange(PropertyChangeEvent evt) { Locale lc = (Locale) evt.getNewValue(); if (lc != null) { rb = WebcamUtils.loadRB(WebcamPanel.class, lc); } } @Override public void webcamOpen(WebcamEvent we) { // if default size has not been provided, then use the one from webcam // device (this will be current webcam resolution) if (defaultSize == null) { setPreferredSize(webcam.getViewSize()); } } @Override public void webcamClosed(WebcamEvent we) { stop(); } @Override public void webcamDisposed(WebcamEvent we) { stop(); } @Override public void webcamImageObtained(WebcamEvent we) { // do nothing } /** * This method returns true if image mirroring is enabled. The default value is false. * * @return True if image is mirrored, false otherwise */ public boolean isMirrored() { return mirrored; } /** * Decide whether or not the image from webcam painted on panel surface will be mirrored. The * image from camera itself is not modified. * * @param mirrored the parameter to control if image should be mirrored */ public void setMirrored(boolean mirrored) { this.mirrored = mirrored; } /** * Return {@link Webcam} used by this panel. * * @return {@link Webcam} */ public Webcam getWebcam() { return webcam; } /** * @return {@link BufferedImage} displayed on {@link WebcamPanel} */ public BufferedImage getImage() { return image; } } static WebcamPanel2 panel; static bool savingOn = true; static double saveEvery = 10.0; static volatile File latestSaved; p { restartWith128MBHeap(); outBuf(50000); substance(); selectWebCam(voidfunc(Webcam cam) { panel = new WebcamPanel2(cam, true); panel.setFPSDisplayed(true); frameIcon(#1009177, exitProgramOnFrameClose(alwaysOnTop(showPackedFrame("JavaX Live WebCam", panel))); bot("WebCam."); doEvery_daemon_now(saveEvery, f saveDefault); }); hideConsole(); } answer { if "save jpeg at *" { saveJPEG(newFile($1), imageFromWebcamPanel(panel)); ret "OK"; } if "latest file" ret latestSaved == null ? "Not saved yet" : "OK " + quote(f2s(latestSaved)); } svoid saveDefault { if (!savingOn) ret; File file = newFile(javaxDataDir(), "WebCam", ("webcam-" + dateWithSecondsForFile() + ".jpg"); saveJPEG(file, imageFromWebcamPanel(panel)); latestSaved = file; }
Began life as a copy of #1013489
download show line numbers debug dex old transpilations
Travelled to 13 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, gwrvuhgaqvyk, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tslmcundralx, tvejysmllsmz, vouqrxazstgt
No comments. add comment
Snippet ID: | #1014901 |
Snippet name: | JavaX Live WebCam - Show live webcam image in frame v5 [try to minimize CPU when iconified - program works, but doesn't make a difference to vanilla WebcamPanel] |
Eternal ID of this version: | #1014901/8 |
Text MD5: | 7750d67fc344e1dcaecf6d54d46f14bb |
Transpilation MD5: | 6c38f054e53b86af88e25be20646b691 |
Author: | stefan |
Category: | javax / desktop / camera |
Type: | JavaX source code (desktop) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2018-05-06 11:38:19 |
Source code size: | 29723 bytes / 1199 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 403 / 1016 |
Version history: | 7 change(s) |
Referenced in: | [show references] |