/*
* Copyright (C) 2011 Jason von Nieda <jason@vonnieda.org>
*
* This file is part of OpenPnP.
*
* OpenPnP is free software: you can redistribute it and/or modify it under the terms of the GNU
* General Public License as published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* OpenPnP is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along with OpenPnP. If not, see
* <http://www.gnu.org/licenses/>.
*
* For more information about OpenPnP visit http://openpnp.org
*/
package org.openpnp.machine.reference.camera;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.beans.PropertyChangeSupport;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.Action;
import org.openpnp.CameraListener;
import org.openpnp.gui.support.Wizard;
import org.openpnp.machine.reference.ReferenceCamera;
import org.openpnp.machine.reference.camera.wizards.ImageCameraConfigurationWizard;
import org.openpnp.model.Configuration;
import org.openpnp.model.LengthUnit;
import org.openpnp.model.Location;
import org.openpnp.spi.PropertySheetHolder;
import org.simpleframework.xml.Attribute;
import org.simpleframework.xml.Element;
import org.simpleframework.xml.core.Commit;
public class ImageCamera extends ReferenceCamera implements Runnable {
private PropertyChangeSupport pcs = new PropertyChangeSupport(this);
@Attribute(required = false)
private int fps = 24;
@Element
private String sourceUri = "classpath://samples/pnp-test/pnp-test.png";
@Attribute(required = false)
private int width = 640;
@Attribute(required = false)
private int height = 480;
private BufferedImage source;
private Thread thread;
public ImageCamera() {
setUnitsPerPixel(new Location(LengthUnit.Millimeters, 0.04233, 0.04233, 0, 0));
try {
setSourceUri(sourceUri);
}
catch (Exception e) {
}
}
@SuppressWarnings("unused")
@Commit
private void commit() throws Exception {
setSourceUri(sourceUri);
}
@Override
public synchronized void startContinuousCapture(CameraListener listener, int maximumFps) {
start();
super.startContinuousCapture(listener, maximumFps);
}
@Override
public synchronized void stopContinuousCapture(CameraListener listener) {
super.stopContinuousCapture(listener);
if (listeners.size() == 0) {
stop();
}
}
private synchronized void stop() {
if (thread != null && thread.isAlive()) {
thread.interrupt();
try {
thread.join();
}
catch (Exception e) {
}
thread = null;
}
}
private synchronized void start() {
if (thread == null) {
thread = new Thread(this);
thread.start();
}
}
public String getSourceUri() {
return sourceUri;
}
public void setSourceUri(String sourceUri) throws Exception {
String oldValue = this.sourceUri;
this.sourceUri = sourceUri;
pcs.firePropertyChange("sourceUri", oldValue, sourceUri);
initialize();
}
@Override
public synchronized BufferedImage internalCapture() {
/*
* Create a buffer that we will render the center tile and it's surrounding tiles to.
*/
BufferedImage frame = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics gFrame = frame.getGraphics();
Location location = getLocation();
double locationX = location.getX();
double locationY = location.getY();
double pixelX = locationX / getUnitsPerPixel().getX();
double pixelY = locationY / getUnitsPerPixel().getY();
int dx1 = (int) (pixelX - (width / 2));
int dy1 = (int) (source.getHeight() - (pixelY + (height / 2)));
gFrame.drawImage(source, 0, 0, width - 1, height - 1, dx1, dy1, dx1 + width - 1,
dy1 + height - 1, null);
gFrame.dispose();
return transformImage(frame);
}
private synchronized void initialize() throws Exception {
stop();
if (sourceUri.startsWith("classpath://")) {
source = ImageIO.read(getClass().getClassLoader()
.getResourceAsStream(sourceUri.substring("classpath://".length())));
}
else {
source = ImageIO.read(new URL(sourceUri));
}
if (listeners.size() > 0) {
start();
}
}
public void run() {
while (!Thread.interrupted()) {
BufferedImage frame = internalCapture();
broadcastCapture(frame);
try {
Thread.sleep(1000 / fps);
}
catch (InterruptedException e) {
return;
}
}
}
@Override
public Wizard getConfigurationWizard() {
return new ImageCameraConfigurationWizard(this);
}
@Override
public String getPropertySheetHolderTitle() {
return getClass().getSimpleName() + " " + getName();
}
@Override
public PropertySheetHolder[] getChildPropertySheetHolders() {
// TODO Auto-generated method stub
return null;
}
}