mirror of
https://github.com/processing/processing4.git
synced 2026-02-03 05:39:18 +01:00
finalizing camera api, added source(), settings(), and format().. also
fixed unhex
This commit is contained in:
@@ -175,10 +175,6 @@ and we don't recommend it at all. nor do we particularly recommend
|
||||
10.2, if you can avoid it. and if you're running 10.4, processing is
|
||||
the least of your worries.
|
||||
|
||||
mouse wheel support only works if you're using java 1.4. the latest
|
||||
version of java will be available via the software update control
|
||||
panel.
|
||||
|
||||
serial port.. we use rxtx (version 2.1_6) to handle serial i/o, which
|
||||
is included with the processing release. unlike previous releases
|
||||
(anything before 57), it no longer requires separate installation.
|
||||
|
||||
@@ -40,12 +40,35 @@ ABOUT REV 0083 -
|
||||
+ shininess(float shiney) takes a float from 0..1 to specify
|
||||
the level of shininess for the current material
|
||||
|
||||
- video camera api should now be finalized:
|
||||
|
||||
+ that whole thing with passing null or "" to the camera constructor
|
||||
was really silly. now either one will just give you the default
|
||||
video input device.
|
||||
|
||||
+ added settings() which will show the settings dialog
|
||||
|
||||
+ source() takes parameters TUNER, COMPOSITE, SVIDEO or COMPONENT
|
||||
to select the input source.
|
||||
|
||||
+ format() takes parameters NTSC, SECAM or PAL
|
||||
|
||||
+ crop(x, y, w, h) (uses the current imageMode from the parent
|
||||
applet) will crop the video before putting it into its PImage.
|
||||
this is almost always used internally because qt likes to add
|
||||
black bars to the image, but you can now specify your own
|
||||
settings to crop things further
|
||||
|
||||
+ noCrop() will remove any cropping, providing a speed increase.
|
||||
|
||||
+ there may be bugs.. things were sometimes hanging on my machine
|
||||
when there were errors
|
||||
|
||||
- link() now works when running as an application. also added
|
||||
open(String filename) which will attempt to launch an application
|
||||
using the shell, or open(String args[]) which will do the same
|
||||
with several command line args.
|
||||
|
||||
-
|
||||
|
||||
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
|
||||
|
||||
@@ -4706,7 +4706,8 @@ public class PApplet extends Applet
|
||||
}
|
||||
|
||||
static final public int unhex(String what) {
|
||||
return Integer.parseInt(what, 16);
|
||||
// has to parse as a Long so that it'll work for numbers bigger than 2^31
|
||||
return (int) (Long.parseLong(what, 16));
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@@ -131,6 +131,7 @@ o yes, and add nf(int what) so that non-padded version works
|
||||
o but don't put commas into the zero-padded version
|
||||
o make nf/nfs/nfp not so weird
|
||||
o nf(PLUS, ...) nf(PAD, ...) nfc(PLUS, ...)
|
||||
X unhex was broken for numbers bigger than 2^31
|
||||
|
||||
|
||||
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
|
||||
35
todo.txt
35
todo.txt
@@ -9,24 +9,38 @@ X get latest sonia from amit
|
||||
X remove particles from current processing
|
||||
X move netscape library out of libs and into build/shared
|
||||
X add serial.stop() just like client/server
|
||||
X border weirdness in PdeEditor panels on windows (fixed in 82)
|
||||
o fix macos readme about how to boost memory size, and 1.3 vs 1.4
|
||||
X actually, this was already in there
|
||||
|
||||
camera
|
||||
o setting the camera should be an index from list()
|
||||
o there might be multiple cameras with the same name
|
||||
X no can do, the function takes a String for the device name
|
||||
o list() should return full list with all sub-components
|
||||
X find the example code from the board
|
||||
X grabbing sub-devices from camera in the lib (via list() or whatever)
|
||||
o actually, need to use numbered indices (multiple w/ same name)
|
||||
o list should be: "0 - Logitech QuickCam (Blah)"
|
||||
o and then use the indices (or the str i guess) to choose
|
||||
X format(NTSC) or PAL or SECAM
|
||||
X source(COMPOSITE) or SVIDEO or COMPONENT
|
||||
X settings() brings up settings dialog
|
||||
|
||||
_ rename video.Camera to video.Video ?
|
||||
_ VideoInput VideoOutput, SoundInput, SoundOutput or AudioInput/AudioOutput
|
||||
_ list() should return full list with all sub-components
|
||||
_ find the example code from the board
|
||||
|
||||
_ add prompt() method to Camera ("" means default, null is prompt)
|
||||
_ let them pass in prompt(), not use null
|
||||
_ setting the camera should be an index from list()
|
||||
_ grabbing sub-devices from camera in the lib (via list() or whatever)
|
||||
_ actually, need to use numbered indices (multiple w/ same name)
|
||||
_ list should be: "0 - Logitech QuickCam (Blah)"
|
||||
_ and then use the indices (or the str i guess) to choose
|
||||
_ null is only bringing up settings dialog, that's wrong
|
||||
|
||||
_ port DbnRecorder?
|
||||
_ do this after beta, not likely to work with java 1.4 on macosx
|
||||
|
||||
_ add prompt() method to serial
|
||||
|
||||
_ remove PdeXxx prefixes on names, make PdeBase into just "Processing"
|
||||
|
||||
_ fix macos readme about how to boost memory size, and 1.3 vs 1.4
|
||||
|
||||
_ update .exe to use new class/package
|
||||
_ update .app to use new class/package
|
||||
_ update linux build and shell scripts for new package
|
||||
@@ -34,9 +48,6 @@ _ update linux build and shell scripts for new package
|
||||
_ make a linux version
|
||||
_ need to fix up the make/dist scripts for linux
|
||||
|
||||
fixed in 82
|
||||
X border weirdness in PdeEditor panels on windows
|
||||
|
||||
|
||||
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
|
||||
|
||||
@@ -35,15 +35,26 @@ import quicktime.std.sg.*;
|
||||
import quicktime.util.RawEncodedImage;
|
||||
|
||||
|
||||
// this is the useful ref page
|
||||
// http://developer.apple.com/documentation/Java/Reference/1.4.1/Java141API_QTJ/constant-values.html
|
||||
|
||||
public class Camera extends PImage implements Runnable {
|
||||
//implements StdQTConstants, StdQTConstants4, Runnable {
|
||||
|
||||
// there are more, but these are all we'll provide for now
|
||||
static public final int COMPOSITE = StdQTConstants.compositeIn; // 0
|
||||
static public final int SVIDEO = StdQTConstants.sVideoIn; // 1
|
||||
static public final int COMPONENT = StdQTConstants.rgbComponentIn; // 2
|
||||
static public final int TUNER = StdQTConstants.tvTunerIn; // 6
|
||||
|
||||
static public final int NTSC = StdQTConstants.ntscIn;
|
||||
static public final int PAL = StdQTConstants.palIn;
|
||||
static public final int SECAM = StdQTConstants.secamIn;
|
||||
|
||||
PApplet parent;
|
||||
Method cameraEventMethod;
|
||||
String name; // keep track for error messages
|
||||
String name; // keep track for error messages (unused)
|
||||
Thread runner;
|
||||
|
||||
//PImage borderImage;
|
||||
//boolean removeBorders = true;
|
||||
boolean available = false;
|
||||
|
||||
/** Temporary storage for the raw image data read directly from the camera */
|
||||
@@ -53,18 +64,24 @@ public class Camera extends PImage implements Runnable {
|
||||
public int dataHeight;
|
||||
public int dataRowBytes;
|
||||
|
||||
/** True if this image is currently being cropped */
|
||||
public boolean crop;
|
||||
|
||||
public int cropX;
|
||||
public int cropY;
|
||||
public int cropW;
|
||||
public int cropH;
|
||||
|
||||
int fps;
|
||||
RawEncodedImage raw;
|
||||
SequenceGrabber capture;
|
||||
public int framerate;
|
||||
|
||||
public RawEncodedImage raw;
|
||||
public SequenceGrabber capture;
|
||||
|
||||
/** the guy who's doing all the work */
|
||||
public SGVideoChannel channel;
|
||||
|
||||
|
||||
static {
|
||||
//System.out.println("Camera init");
|
||||
try {
|
||||
QTSession.open();
|
||||
} catch (QTException e) {
|
||||
@@ -81,11 +98,11 @@ public class Camera extends PImage implements Runnable {
|
||||
|
||||
|
||||
public Camera(PApplet parent, int requestWidth, int requestHeight) {
|
||||
this(parent, "", requestWidth, requestHeight, 30);
|
||||
this(parent, null, requestWidth, requestHeight, 30);
|
||||
}
|
||||
|
||||
public Camera(PApplet parent, int reqWidth, int reqHeight, int fps) {
|
||||
this(parent, "", reqWidth, reqHeight, fps);
|
||||
public Camera(PApplet parent, int reqWidth, int reqHeight, int framerate) {
|
||||
this(parent, null, reqWidth, reqHeight, framerate);
|
||||
}
|
||||
|
||||
public Camera(PApplet parent, String name, int reqWidth, int reqHeight) {
|
||||
@@ -93,26 +110,10 @@ public class Camera extends PImage implements Runnable {
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
quicktime.QTSession.open();
|
||||
quicktime.std.sg.SequenceGrabber sg = new quicktime.std.sg.SequenceGrabber();
|
||||
quicktime.std.sg.SGVideoChannel sc = new quicktime.std.sg.SGVideoChannel(sg);
|
||||
quicktime.std.sg.VideoDigitizer vd = sc.getDigitizerComponent();
|
||||
println( "dv.getNumberOfInputs :" ); println( vd.getNumberOfInputs() ); println();
|
||||
//change line below to set input source
|
||||
vd.setInput(1);
|
||||
//
|
||||
println( "dv.getInput :" ); println( vd.getInput() ); println();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* If 'name' is the empty string, don't set a specific device,
|
||||
* which means that QuickTime will use that last device used by
|
||||
* a QuickTime application. If name is set to null, a prompt
|
||||
* will show up, allowing the user to choose the good stuff.
|
||||
* If 'name' is null or the empty string, it won't set a specific
|
||||
* device, which means that QuickTime will use that last device
|
||||
* used by a QuickTime application.
|
||||
* <P>
|
||||
* If the following function:
|
||||
* public void cameraEvent(Camera c)
|
||||
@@ -120,100 +121,48 @@ public class Camera extends PImage implements Runnable {
|
||||
* time a new frame is available from the camera.
|
||||
*/
|
||||
public Camera(PApplet parent, String name,
|
||||
int requestWidth, int requestHeight, int fps) {
|
||||
int requestWidth, int requestHeight, int framerate) {
|
||||
this.parent = parent;
|
||||
this.name = name;
|
||||
this.fps = fps;
|
||||
this.framerate = framerate;
|
||||
|
||||
try {
|
||||
/*
|
||||
QTSession.open();
|
||||
QTRuntimeException.registerHandler(new QTRuntimeHandler() {
|
||||
public void exceptionOccurred(QTRuntimeException e,
|
||||
Object obj, String s, boolean flag) {
|
||||
System.err.println("Problem inside Camera");
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
*/
|
||||
//System.out.println("0");
|
||||
|
||||
QDRect qdrect = new QDRect(requestWidth, requestHeight);
|
||||
QDGraphics qdgraphics = new QDGraphics(qdrect);
|
||||
|
||||
//System.out.println("0a");
|
||||
|
||||
capture = new SequenceGrabber();
|
||||
//System.out.println("0b");
|
||||
capture.setGWorld(qdgraphics, null);
|
||||
|
||||
//System.out.println("0c");
|
||||
|
||||
// CRASHING HERE ON OSX
|
||||
SGVideoChannel channel = new SGVideoChannel(capture);
|
||||
//System.out.println("0c1");
|
||||
channel = new SGVideoChannel(capture);
|
||||
channel.setBounds(qdrect);
|
||||
//System.out.println("0c2");
|
||||
channel.setUsage(2); // what is this usage number?
|
||||
//System.out.println("0c3");
|
||||
capture.startPreview(); // maybe this comes later?
|
||||
|
||||
//System.out.println("0d");
|
||||
|
||||
PixMap pixmap = qdgraphics.getPixMap();
|
||||
raw = pixmap.getPixelData();
|
||||
|
||||
//System.out.println("0e");
|
||||
|
||||
/*
|
||||
if (name == null) {
|
||||
channel.settingsDialog();
|
||||
|
||||
} else if (name.length() > 0) {
|
||||
channel.setDevice(name);
|
||||
}
|
||||
//System.out.println("0f");
|
||||
//channel.setDevice("Logitech QuickCam Express-WDM");
|
||||
/*
|
||||
if (showDialog) channel.settingsDialog();
|
||||
SGDeviceList list = channel.getDeviceList(0);
|
||||
System.out.println("count is " + list.getCount());
|
||||
for (int i = 0; i < list.getCount(); i++) {
|
||||
System.out.println(list.getDeviceName(i).getName());
|
||||
}
|
||||
//System.out.println(channel.getSettings());
|
||||
*/
|
||||
if ((name != null) && (name.length() > 0)) {
|
||||
channel.setDevice(name);
|
||||
}
|
||||
|
||||
//int grabWidthBytes = raw.getRowBytes();
|
||||
dataRowBytes = raw.getRowBytes();
|
||||
dataWidth = dataRowBytes / 4;
|
||||
|
||||
//System.out.println("row bytes " + raw.getRowBytes() + " " +
|
||||
// (raw.getRowBytes() / 4));
|
||||
//int extraBytes = dataRowBytes - requestWidth*4;
|
||||
//int extraPixels = extraBytes / 4;
|
||||
//int videoWidth = requestWidth + extraPixels;
|
||||
dataHeight = raw.getSize() / dataRowBytes;
|
||||
|
||||
//System.out.println("height req, actual: " + requestHeight +
|
||||
// " " + dataHeight);
|
||||
|
||||
if (dataWidth != requestWidth) {
|
||||
crop = true;
|
||||
cropX = 0;
|
||||
cropY = 0;
|
||||
cropW = requestWidth;
|
||||
cropH = requestHeight;
|
||||
|
||||
/*
|
||||
System.out.println("dataWidth is " + dataWidth +
|
||||
" not " + requestWidth);
|
||||
if (removeBorders) {
|
||||
int bpixels[] = new int[dataWidth * requestHeight];
|
||||
borderImage = new PImage(bpixels, dataWidth, requestHeight, RGB);
|
||||
} else {
|
||||
requestWidth = dataWidth;
|
||||
}
|
||||
*/
|
||||
}
|
||||
// initialize my PImage self
|
||||
super.init(requestWidth, requestHeight, RGB);
|
||||
@@ -229,19 +178,17 @@ public class Camera extends PImage implements Runnable {
|
||||
new Class[] { Camera.class });
|
||||
} catch (Exception e) {
|
||||
// no such method, or an error.. which is fine, just ignore
|
||||
//e.printStackTrace();
|
||||
}
|
||||
|
||||
} catch (StdQTException qte) {
|
||||
//qte.printStackTrace();
|
||||
|
||||
int errorCode = qte.errorCode();
|
||||
// where's the friggin constant for this?
|
||||
if (errorCode == -9405) {
|
||||
if (errorCode == Errors.couldntGetRequiredComponent) {
|
||||
// this can happen when the camera isn't available or
|
||||
// wasn't shut down properly
|
||||
parent.die("The camera (or VDIG) is not " +
|
||||
"installed correctly (see readme.txt).", qte);
|
||||
parent.die("No camera could be found, " +
|
||||
"or the VDIG is not installed correctly.", qte);
|
||||
} else {
|
||||
parent.die("Error while setting up Camera", qte);
|
||||
}
|
||||
@@ -252,11 +199,20 @@ public class Camera extends PImage implements Runnable {
|
||||
|
||||
|
||||
/**
|
||||
* True if a frame is ready to be read. Example:
|
||||
* True if a frame is ready to be read.
|
||||
* <PRE>
|
||||
* // put this somewhere inside draw
|
||||
* if (camera.available()) camera.read();
|
||||
* <P>
|
||||
* </PRE>
|
||||
* Alternatively, you can use cameraEvent(Camera c) to notify you
|
||||
* whenever available() is set to true.
|
||||
* whenever available() is set to true. In which case, things might
|
||||
* look like this:
|
||||
* <PRE>
|
||||
* public void cameraEvent(Camera c) {
|
||||
* c.read();
|
||||
* // do something exciting now that c has been updated
|
||||
* }
|
||||
* </PRE>
|
||||
*/
|
||||
public boolean available() {
|
||||
return available;
|
||||
@@ -291,6 +247,13 @@ public class Camera extends PImage implements Runnable {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove the cropping (if any) of the image.
|
||||
* <P>
|
||||
* By default, cropping is often enabled to trim out black pixels.
|
||||
* But if you'd rather deal with them yourself (so as to avoid
|
||||
* an extra lag while the data is moved around) you can shut it off.
|
||||
*/
|
||||
public void noCrop() {
|
||||
crop = false;
|
||||
}
|
||||
@@ -325,21 +288,7 @@ public class Camera extends PImage implements Runnable {
|
||||
sourceOffset += dataWidth;
|
||||
destOffset += width;
|
||||
}
|
||||
|
||||
/*
|
||||
if (borderImage != null) { // need to remove borders
|
||||
raw.copyToArray(0, borderImage.pixels,
|
||||
0, borderImage.width * borderImage.height);
|
||||
int borderIndex = 0;
|
||||
int targetIndex = 0;
|
||||
for (int i = 0; i < height; i++) {
|
||||
System.arraycopy(borderImage.pixels, borderIndex,
|
||||
pixels, targetIndex, width);
|
||||
borderIndex += borderImage.width;
|
||||
targetIndex += width;
|
||||
}
|
||||
*/
|
||||
} else { // just copy directly
|
||||
} else { // no crop, just copy directly
|
||||
raw.copyToArray(0, pixels, 0, width * height);
|
||||
}
|
||||
//long t2 = System.currentTimeMillis();
|
||||
@@ -378,7 +327,7 @@ public class Camera extends PImage implements Runnable {
|
||||
}
|
||||
|
||||
try {
|
||||
Thread.sleep(1000 / fps);
|
||||
Thread.sleep(1000 / framerate);
|
||||
} catch (InterruptedException e) { }
|
||||
}
|
||||
}
|
||||
@@ -388,13 +337,13 @@ public class Camera extends PImage implements Runnable {
|
||||
* Set the framerate for how quickly new frames are read
|
||||
* from the camera.
|
||||
*/
|
||||
public void framerate(int ifps) {
|
||||
if (ifps <= 0) {
|
||||
public void framerate(int iframerate) {
|
||||
if (iframerate <= 0) {
|
||||
System.err.println("Camera: ignoring bad framerate of " +
|
||||
ifps + " fps.");
|
||||
iframerate + " fps.");
|
||||
return;
|
||||
}
|
||||
fps = ifps;
|
||||
framerate = iframerate;
|
||||
}
|
||||
|
||||
|
||||
@@ -436,11 +385,78 @@ public class Camera extends PImage implements Runnable {
|
||||
|
||||
|
||||
/**
|
||||
* Shows the settings dialog for this channel.
|
||||
* Set the format to ask for from the video digitizer:
|
||||
* TUNER, COMPOSITE, SVIDEO, or COMPONENT.
|
||||
* <P>
|
||||
* The constants are just aliases to the constants returned from
|
||||
* QuickTime's getInputFormat() function, so any valid constant from
|
||||
* that will work just fine.
|
||||
*/
|
||||
//public void prompt() {
|
||||
//channel.settingsDialog();
|
||||
//}
|
||||
public void source(int which) {
|
||||
try {
|
||||
VideoDigitizer digitizer = channel.getDigitizerComponent();
|
||||
int count = digitizer.getNumberOfInputs();
|
||||
for (int i = 0; i < count; i++) {
|
||||
//System.out.println("format " + digitizer.getInputFormat(i));
|
||||
if (digitizer.getInputFormat(i) == which) {
|
||||
digitizer.setInput(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw new RuntimeException("The specified source() is not available.");
|
||||
|
||||
} catch (StdQTException e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException("Could not set the video input source.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the video format standard to use on the
|
||||
* video digitizer: NTSC, PAL, or SECAM.
|
||||
* <P>
|
||||
* The constants are just aliases to the constants used for
|
||||
* QuickTime's setInputStandard() function, so any valid
|
||||
* constant from that will work just fine.
|
||||
*/
|
||||
public void format(int which) {
|
||||
try {
|
||||
VideoDigitizer digitizer = channel.getDigitizerComponent();
|
||||
digitizer.setInputStandard(which);
|
||||
} catch (StdQTException e) {
|
||||
e.printStackTrace();
|
||||
//throw new RuntimeException("Could not set the video input format");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Show the settings dialog for this input device.
|
||||
*/
|
||||
public void settings() {
|
||||
try {
|
||||
channel.settingsDialog();
|
||||
} catch (StdQTException qte) {
|
||||
int errorCode = qte.errorCode();
|
||||
if (errorCode != Errors.userCanceledErr) {
|
||||
qte.printStackTrace();
|
||||
throw new RuntimeException("error inside Camera.settings()");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
public String[] listInputs() {
|
||||
VideoDigitizer digitizer = channel.getDigitizerComponent();
|
||||
int count = digitizer.getNumberOfInputs();
|
||||
|
||||
String outgoing[] = new String[count];
|
||||
//digitizer.setInput(2); // or something
|
||||
//DigitizerInfo di = digitizer.getDigitizerInfo()
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user