/*
* jmfcam05s.java 01.01a 07.11.2006
*
* Copyright (c) 2006 Andy Dyble. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
* and associated documentation files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the name of the author shall not be used in
* advertising or otherwise to promote the sale, use or other dealings in this Software without
* prior written authorization from the author.
*
*/
/*
* Java Media Framework
*
* Copyright (c) 1999-2001 Sun Microsystems, Inc. All Rights Reserved.
*
* Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
* modify and redistribute this software in source and binary code form,
* provided that i) this copyright notice and license appear on all copies of
* the software; and ii) Licensee does not utilize the software in a manner
* which is disparaging to Sun.
*
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
* IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
* NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
* LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
* LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
* INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
* CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
* OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
* This software is not designed or intended for use in on-line control of
* aircraft, air traffic, aircraft navigation or aircraft communications; or in
* the design, construction, operation or maintenance of any nuclear
* facility. Licensee represents and warrants that it will not use or
* redistribute the Software for such purposes.
*/
import java.awt.*;
import java.util.*;
import javax.media.*;
import javax.media.protocol.*;
import javax.media.control.*;
import javax.media.format.*;
import java.awt.image.*;
import java.net.*;
import javax.media.util.BufferToImage;
/**
* This is the primary class to run. It gathers an image stream and drives the processing.
*
*/
public class jmfcam05s extends Frame
{
static volatile boolean active;
DataSource dataSource;
PushBufferStream pbs;
Buffer b;
byte[] inData;
Vector camImgSize = new Vector();
Vector camCapDevice = new Vector();
Vector camCapFormat = new Vector();
static int camWidth;
static int camHeight;
int camFPS;
int camImgSel;
/**
* Main method to instance and run class
*
*/
public static void main(String[] args)
{
jmfcam05s jmfcam = new jmfcam05s();
}
/**
* Constructor and processing method for image stream from a cam
*
*/
public jmfcam05s()
{
active = true;
// Select webcam format
fetchDeviceFormats();
camImgSel=0; // first format, or otherwise as desired
String camS = (String)camImgSize.elementAt(camImgSel);
int pos_x = camS.indexOf("x");
String widS = camS.substring(0,pos_x);
String hgtS = camS.substring(pos_x+1,camS.length());
camWidth = Integer.parseInt(widS.trim());
camHeight = Integer.parseInt(hgtS.trim());
camFPS = 30;
// Setup data source
fetchDeviceDataSource();
Thread.yield();
createPBDSource();
Thread.yield();
try{dataSource.start();}catch(Exception e){System.out.println("Exception dataSource.start() "+e);}
Thread.yield();
try{Thread.sleep(1000);}catch(Exception e){} // to let camera settle ahead of processing
// Some gui setup
setLayout(new FlowLayout());
setTitle("Video Source");
imgPanel currPanel = new imgPanel(new Dimension(camWidth,camHeight));
add(currPanel);
pack();Thread.yield();pack();
setLocation(10,20);
setVisible(true);
Image resultImage = this.createImage(camWidth,camHeight);
Graphics resultGraphics = resultImage.getGraphics();
resultGraphics.setFont(new Font("Arial", 0, 12));
resultGraphics.setColor(Color.cyan);
int[] inpix=new int[camWidth * camHeight];int[] outpix=new int[camWidth * camHeight];
b=new Buffer();
DirectColorModel dcm = new DirectColorModel(32, 0x00FF0000, 0x0000FF00, 0x000000FF);
MemoryImageSource sourceImage = new MemoryImageSource(camWidth, camHeight, dcm, outpix, 0, camWidth);
Image outputImage;
// BufferToImage bti = new BufferToImage((VideoFormat)camCapFormat.elementAt(camImgSel));
boolean frameOK=false;
while(active==true)
{
frameOK = camFetchFrame();
if(frameOK==false) // inData is null
{
try{Thread.sleep(5);}catch(Exception e){}
continue;
}
// Create pixel array from above ColorModel
createPixels(inpix);
process(inpix,outpix); // for effects or filters etc eg grayscale(inpix,outpix);
outputImage = createImage(sourceImage);
// // or directly to awt image
// outputImage=bti.createImage(b);
// Draw frame and text and any other graphics
resultGraphics.drawImage(outputImage,0,0,this);
resultGraphics.drawString("Testing 123 ExactFutures",20,20);
currPanel.setImage(resultImage);
try{Thread.sleep(5);}catch(Exception e){}
Thread.yield();
}
}
/**
* Gets an image via the cam
*
*/
boolean camFetchFrame()
{
try
{
pbs.read(b);
inData=(byte[])b.getData();
if(b.isDiscard())inData=null;
Thread.yield();
}
catch(Exception e){}
if(inData==null)return false;
else
return true;
}
/**
* Creates array of rgb pixel values for cam
*
*/
void createPixels(int[] prepix) // may need to amend this for other OS ColorModels
{
boolean flip=true;
{
int srcPtr = 0;
int dstPtr = 0;
int dstInc = 0;
if(flip)
{
dstPtr = camWidth * (camHeight - 1);
dstInc = -2 * camWidth;
}
for(int y = 0; y < camHeight; y++)
{
for(int x = 0; x < camWidth; x++)
{
byte red = inData[srcPtr + 2];
byte green = inData[srcPtr + 1];
byte blue = inData[srcPtr];
int pixel = (red & 0xff) << 16 | (green & 0xff) << 8 | (blue & 0xff) << 0;
prepix[dstPtr] = pixel;
srcPtr += 3;
dstPtr += 1;
}
dstPtr += dstInc;
}
}
Thread.yield();
}
/**
* Processes the frame data
*
*/
void process(int[] prepix, int[] postpix)
{
// R = (pixels[index] >> 16) & 0xff;
// G = (pixels[index] >> 8) & 0xff;
// B = (pixels[index]) & 0xff;
// pixels[index] = (R & 0xff) << 16 | (G & 0xff) << 8 | (B & 0xff) << 0;
// this just copies in to out
System.arraycopy(prepix, 0, postpix, 0, prepix.length);
}
/**
* Processes the frame data to grayscale - example process
*
*/
void grayscale(int[] prepix, int[] post