//import java.applet.*; //import java.awt.*; //import java.net.*; //import java.io.*; //import java.awt.image.*; //import java.util.Hashtable; import java.applet.Applet; import java.awt.image.*; import java.awt.*; import java.util.Hashtable; import java.net.*; import java.io.*; import java.lang.Number; import java.lang.*; import java.awt.event.*; // // Read data from digital camera on PicoWeb, convert to image, and display // public class nickcam extends Applet { static final int ALPHA = 24; static final int RED = 16; static final int GREEN = 8; static final int BLUE = 0; static final int NONE = 0; static final int FILL = 1 << 0; static final int SHARPEN = 1 << 1; static final int ALL = (FILL | SHARPEN); String ErrMsg = "???"; byte[] RawPixels; // where to store raw pixel data from camera Image image; int w = 164; int h = 120; int mag = 1; int action = ALL; public int GetPix(int color, int pixels[], int x, int y, int w, int h) { if (x < 0) x = 0; if (x >= w) x = w-1; if (y < 0) y = 0; if (y >= h) y = h-1; int val = pixels[w * y + x]; switch (color) { case ALPHA: val = val >> ALPHA; break; case RED : val = val >> RED; break; case GREEN: val = val >> GREEN; break; case BLUE : val = val >> BLUE; break; } return (val & 255); } public void PutPix(int val, int color, int pixels[], int x, int y, int w, int h) { int nval; if (x < 0) x = 0; if (x >= w) x = w-1; if (y < 0) y = 0; if (y >= h) y = h-1; if (val < 0) val = 0; if (val > 255) val = 255; switch (color) { case ALPHA: nval = (pixels[w * y + x] & (~(255 << ALPHA))) | (val << ALPHA); break; case RED : nval = (pixels[w * y + x] & (~(255 << RED))) | (val << RED); break; case GREEN: nval = (pixels[w * y + x] & (~(255 << GREEN))) | (val << GREEN); break; case BLUE : nval = (pixels[w * y + x] & (~(255 << BLUE))) | (val << BLUE); break; default: nval = pixels[w * y + x]; break; } pixels[w * y + x] = nval; } void MakeImage(int action, byte PixBuf[], int w, int h) { int bayers[] = new int[w * h]; int sharp_bayers[] = new int[w * h]; // clear pixel array (set alpha channel) int OFF = 7; for (int y = 0; y < h; ++y) { for (int x = 0; x < w; ++x) { bayers[w * y + x] = 255 << ALPHA; sharp_bayers[w * y + x] = 255 << ALPHA; } } // // Bayer Color Pattern (camera pixels) // // +--------+--------+ // | | | // | | | // | Green1 | Red | // | | | // | | | // +--------+--------+ // | | | // | | | // | Blue | Green2 | // | | | // | | | // +--------+--------+ // // Read from camera: // // (1) One row of red pixels values (0-255) // (2) One row of green1 pixels values (0-255) // (3) One row of green2 pixels values (0-255) // (4) One row of blue pixels values (0-255) // // // Unscramble into sparse pixel array // // red for (int y = 0; y < h; ++y) { int xoff = 0; for (int x = 0; x < w; ++x) { if (((y&1) == 0) && (x < (w / 2))) { int off = y * w + x + OFF; int val = ((int)PixBuf[off]) & 255; PutPix(val, RED, bayers, (xoff+1)+2, y, w, h); xoff += 2; } } } // green1 for (int y = 0; y < h; y += 1) { int xoff = 0; for (int x = 0; x < w; x += 1) { if (((y&1) == 0) && (x >= (w / 2))) { int off = y * w + x + OFF; int val = ((int)PixBuf[off]) & 255; PutPix(val, GREEN, bayers, xoff-2, y, w, h); xoff += 2; } } } // green2 for (int y = 0; y < h; y += 1) { int xoff = 0; for (int x = 0; x < w; x += 1) { if (((y&1) == 1) && (x < (w / 2))) { int off = y * w + x + OFF; int val = ((int)PixBuf[off]) & 255; PutPix(val, GREEN, bayers, (xoff+1)+2, y, w, h); xoff += 2; } } } // blue for (int y = 0; y < h; y += 1) { int xoff = 0; for (int x = 0; x < w; x += 1) { if (((y&1) == 1) && (x >= (w / 2))) { int off = y * w + x + OFF; int val = ((int)PixBuf[off]) & 255; PutPix(val, BLUE, bayers, xoff-2, y, w, h); xoff += 2; } } } // // Fill in missing pixels in Bayer array // if ((action & FILL) != 0) for (int y = 0; y < h; ++y) { for (int x = 0; x < w; ++x) { int val; // Fill in missing green pixels if ((((x&1) == 1) && ((y&1) == 0)) || (((x&1) == 0) && ((y&1) == 1))) { val = (GetPix(GREEN, bayers, x , y-1, w, h) + GetPix(GREEN, bayers, x-1, y , w, h) + GetPix(GREEN, bayers, x+1, y , w, h) + GetPix(GREEN, bayers, x , y+1, w, h)) >> 2; PutPix(val, GREEN, bayers, x, y, w, h); } // Fill in missing red/blue pixels (same line) if (((x&1) == 0) && ((y&1) == 0)) { // green1 (need red/blue) val = (GetPix(RED, bayers, x-1, y , w, h) + GetPix(RED, bayers, x+1, y , w, h)) >> 1; PutPix(val, RED, bayers, x, y, w, h); val = (GetPix(BLUE, bayers, x , y-1, w, h) + GetPix(BLUE, bayers, x , y+1, w, h)) >> 1; PutPix(val, BLUE, bayers, x, y, w, h); } if (((x&1) == 1) && ((y&1) == 1)) { // green2 (need red/blue) val = (GetPix(BLUE, bayers, x-1, y , w, h) + GetPix(BLUE, bayers, x+1, y , w, h)) >> 1; PutPix(val, BLUE, bayers, x, y, w, h); val = (GetPix(RED, bayers, x , y-1, w, h) + GetPix(RED, bayers, x , y+1, w, h)) >> 1; PutPix(val, RED, bayers, x, y, w, h); } // Fill in missing red/blue pixels (different lines) if (((x&1) == 0) && ((y&1) == 1)) { // blue (need red) val = (GetPix(RED, bayers, x+1, y-1, w, h) + GetPix(RED, bayers, x-1, y-1, w, h) + GetPix(RED, bayers, x+1, y+1, w, h) + GetPix(RED, bayers, x-1, y+1, w, h)) >> 2; PutPix(val, RED, bayers, x, y, w, h); } if (((x&1) == 1) && ((y&1) == 0)) { // red (need blue) val = (GetPix(BLUE, bayers, x+1, y-1, w, h) + GetPix(BLUE, bayers, x-1, y-1, w, h) + GetPix(BLUE, bayers, x+1, y+1, w, h) + GetPix(BLUE, bayers, x-1, y+1, w, h)) >> 2; PutPix(val, BLUE, bayers, x, y, w, h); } } } // Sharpen image if ((action & SHARPEN) != 0) { double f = 0.75; // sharpness (0=none) String s = getParameter("sharpness"); if (s != null) { try { //f = Float.parseFloat(s); f = Float.valueOf(s).floatValue(); } catch (Exception e) { /* ignore */ } } for (int y = 0; y < h; ++y) { for (int x = 0; x < w; ++x) { for (int i = 0; i < 3; ++i) { int color = 0; switch (i) { case 0: color = RED; break; case 1: color = GREEN; break; case 2: color = BLUE; break; } int val = ((int)( GetPix(color, bayers, x-1, y , w, h) * -f + GetPix(color, bayers, x , y-1, w, h) * -f + GetPix(color, bayers, x , y , w, h) * (1+4*f) + GetPix(color, bayers, x , y+1, w, h) * -f + GetPix(color, bayers, x-1, y , w, h) * -f )); PutPix(val, color, sharp_bayers, x, y, w, h); } } } for (int y = 0; y < h; ++y) { for (int x = 0; x < w; ++x) { bayers[w * y + x] = sharp_bayers[w * y + x]; } } } // Make a black border for (int y = 0; y < h; y += 1) { int size = 4; for (int x = 0; x < w; x += 1) { if (x < size || x >= w - size) bayers[w * (y) + (x)] = 255 << 24; if (y < size || y >= h - size) bayers[w * (y) + (x)] = 255 << 24; } } image = createImage(new MemoryImageSource(w, h, bayers, 0, w)); } boolean CommandCamera(String command) { try { // Open URL back to Web server (use getCodeBase method // to find host name of PicoWeb ErrMsg = getParameter("host"); if (ErrMsg == null) ErrMsg = getCodeBase() + ""; else ErrMsg = "http://" + ErrMsg + "/"; ErrMsg = ErrMsg + command; URL url = new URL(ErrMsg); // Open a URLConnection to the URL URLConnection urlConn = url.openConnection(); // Use ByteArrayOutputStream as a temporary container. // Once finished reading, we convert it to a byte array. ByteArrayOutputStream tempBuffer; tempBuffer = new ByteArrayOutputStream(); // Get an input stream to this URL InputStream instream = urlConn.getInputStream(); // Read the URL data stream and copy bytes to temporary buffer int ch; int count = 0; while ((ch = instream.read()) >= 0) { tempBuffer.write(ch); ++count; } ErrMsg = count + " bytes read from camera"; System.out.println(count+" bytes read"); if (count <= 3) { ErrMsg = "Camera may be off"; return false; } // Convert the temp buffer to a byte array RawPixels = tempBuffer.toByteArray(); return true; } catch (Exception e) { e.printStackTrace(); return false; } } boolean SnapPhoto() { if (CommandCamera(getParameter("zero"))) { if (CommandCamera(getParameter("grab"))) { return GetPhoto(); } } return false; } boolean GetPhoto() { image = null; if (CommandCamera(getParameter("zero"))) { if (CommandCamera(getParameter("upload"))) { // Turn raw camera pixels into "real" image MakeImage(ALL, RawPixels, w, h); return true; } } return false; } public void init() { setBackground(Color.black); enableEvents(AWTEvent.MOUSE_EVENT_MASK); GetPhoto(); } public void paint(Graphics g) { g.setColor(Color.green); Font textFont = new Font("TimesRoman", Font.PLAIN, 14); g.setFont(textFont); if (RawPixels == null) { g.drawString("Camera access error! ("+ErrMsg+")", 10, 30); } else { if (image == null) { g.drawString("Can't make image ("+ErrMsg+")", 10, 30); } else { Insets insets = getInsets(); int x = insets.left, y = insets.top; ///int gw = g.getClipBounds().width; ///int gh = g.getClipBounds().height; int gw = getSize().width; int gh = getSize().height; int w = (mag * gw) / 4; int h = (mag * gh) / 4; x += (gw - w) / 2; y += (gh - h) / 2; g.drawImage(image, x, y, w, h, this); } } } public void processMouseEvent(MouseEvent e) { switch(e.getID()) { case MouseEvent.MOUSE_PRESSED: int mods = e.getModifiers(); System.out.println("mods="+mods); if ((mods & MouseEvent.BUTTON2_MASK) != 0) { System.out.println("Middle button pressed"); if (RawPixels != null) { switch (action) { case ALL: action = NONE; break; case NONE: action = FILL; break; case FILL: action = ALL; break; } MakeImage(action, RawPixels, w, h); } } else if ((mods & MouseEvent.BUTTON1_MASK) != 0){ System.out.println("Left button pressed"); mag *= 2; if (mag > 4) mag = 1; } else if ((mods & MouseEvent.BUTTON3_MASK) != 0) { System.out.println("Right button pressed"); SnapPhoto(); } repaint(); break; } super.processMouseEvent(e); } }