/* * 作成日: 2008/05/24 */ package jp.ac.fit.asura.nao.vision; import static jp.ac.fit.asura.nao.vision.VisionUtils.getBlue; import static jp.ac.fit.asura.nao.vision.VisionUtils.getGreen; import static jp.ac.fit.asura.nao.vision.VisionUtils.getRed; import java.awt.Color; import java.io.IOException; import java.io.InputStream; import java.nio.ByteBuffer; import java.nio.IntBuffer; import java.util.Arrays; import jp.ac.fit.asura.nao.Image; import jp.ac.fit.asura.nao.Camera.PixelFormat; import jp.ac.fit.asura.nao.Image.BufferType; import jp.ac.fit.asura.nao.misc.TMap; /** * @author $Author: sey $ * * @version $Id: GCD.java 709 2008-11-23 07:40:31Z sey $ * */ public class GCD { public static final byte cORANGE = 0; public static final byte cCYAN = 1; public static final byte cGREEN = 2; public static final byte cYELLOW = 3; // public static final byte cPINK = 4; public static final byte cBLUE = 5; public static final byte cRED = 6; public static final byte cWHITE = 7; // public static final byte cFGREEN = 7; public static final byte cBLACK = 9; public static final int COLOR_NUM = 10; private byte[] yvuPlane; private byte[] tmap; public void loadTMap(String fileName) throws IOException { TMap ppm = new TMap(); ClassLoader cl = getClass().getClassLoader(); InputStream is = cl.getResourceAsStream(fileName); assert is != null; ppm.read(is); is.close(); this.tmap = ppm.getData(); } public void detect(Image image, byte[] gcdPlane) { if (image.getBufferType() == BufferType.INT) { IntBuffer ib = image.getIntBuffer(); assert ib != null; detect(ib, gcdPlane, image.getPixelFormat()); } else if (image.getBufferType() == BufferType.BYTES) { ByteBuffer bb = image.getByteBuffer(); assert bb != null; detect(bb, gcdPlane, image.getPixelFormat()); } } protected void detect(ByteBuffer plane, byte[] gcdPlane, PixelFormat format) { if (format == PixelFormat.YUYV) { detectYuyv(plane, gcdPlane); } else { assert false; } } protected void detect(IntBuffer plane, byte[] gcdPlane, PixelFormat format) { int length = plane.remaining(); if (format == PixelFormat.RGB444) { if (yvuPlane == null || yvuPlane.length != length * 3) { yvuPlane = new byte[length * 3]; } rgb2yvu(plane, yvuPlane); detectYvu(yvuPlane, gcdPlane); } else { assert false; } } public static void yuyv2yvu(ByteBuffer yuyvPlane, byte[] yvuPlane) { yuyvPlane.position(0); assert yuyvPlane.remaining() * 6 == yvuPlane.length * 4 : yvuPlane; for (int i = 0; i < yvuPlane.length;) { byte y1 = yuyvPlane.get(); byte u = yuyvPlane.get(); byte y2 = yuyvPlane.get(); byte v = yuyvPlane.get(); yvuPlane[i++] = y1; yvuPlane[i++] = v; yvuPlane[i++] = u; yvuPlane[i++] = y2; yvuPlane[i++] = v; yvuPlane[i++] = u; } yuyvPlane.position(0); } public static void rgb2yvu(IntBuffer plane, byte[] yvuPlane) { assert plane.remaining() * 3 == yvuPlane.length; plane.mark(); for (int i = 0; i < yvuPlane.length;) { int pixel = plane.get(); int r = getRed(pixel); int g = getGreen(pixel); int b = getBlue(pixel); int y = clipping((int) (0.257f * r + 0.504f * g + 0.098f * b + 16), 0, 255); int u = clipping( (int) (-0.148f * r - 0.291f * g + 0.439f * b + 128), 0, 255); int v = clipping( (int) (0.439f * r - 0.368f * g - 0.071f * b + 128), 0, 255); yvuPlane[i++] = (byte) y; yvuPlane[i++] = (byte) v; yvuPlane[i++] = (byte) u; } plane.reset(); } public static void gcd2rgb(byte[] gcdPlane, int[] rgbPlane) { for (int i = 0; i < gcdPlane.length; i++) { switch (gcdPlane[i]) { case cORANGE: rgbPlane[i] = Color.ORANGE.getRGB(); break; case cCYAN: rgbPlane[i] = Color.CYAN.getRGB(); break; case cBLUE: rgbPlane[i] = Color.BLUE.getRGB(); break; case cGREEN: rgbPlane[i] = Color.GREEN.getRGB(); break; case cRED: rgbPlane[i] = Color.RED.getRGB(); break; case cWHITE: rgbPlane[i] = Color.WHITE.getRGB(); break; case cYELLOW: rgbPlane[i] = Color.YELLOW.getRGB(); break; case cBLACK: rgbPlane[i] = Color.BLACK.getRGB(); break; default: rgbPlane[i] = Color.GRAY.getRGB(); } } } public static void gcd2rgb(byte[] gcdPlane, byte[] rgbPlane) { for (int i = 0; i < gcdPlane.length; i++) { Color c; switch (gcdPlane[i]) { case cORANGE: c = Color.ORANGE; break; case cCYAN: c = Color.CYAN; break; case cBLUE: c = Color.BLUE; break; case cGREEN: c = Color.GREEN; break; case cRED: c = Color.RED; break; case cWHITE: c = Color.WHITE; break; case cYELLOW: c = Color.YELLOW; break; case cBLACK: c = Color.BLACK; break; default: c = Color.GRAY; } rgbPlane[3 * i] = (byte) c.getRed(); rgbPlane[3 * i + 1] = (byte) c.getGreen(); rgbPlane[3 * i + 2] = (byte) c.getBlue(); } } private void detectYvu(byte[] yvuPlane, byte[] gcdPlane) { assert tmap != null; assert yvuPlane.length == gcdPlane.length * 3; int j = 0; for (int i = 0; i < gcdPlane.length; i++) { byte y = yvuPlane[j++]; byte v = yvuPlane[j++]; byte u = yvuPlane[j++]; // 11110000 = F0 // 11111100 = FC // 1111000000000000 // 0000111111000000 gcdPlane[i] = tmap[(y & 0xF0) << 8 | (v & 0xFC) << 4 | (u & 0xFC) >>> 2]; } } private void detectYuyv(ByteBuffer yuyvPlane, byte[] gcdPlane) { assert tmap != null; assert yuyvPlane.remaining() == gcdPlane.length * 4 / 2 : yuyvPlane; yuyvPlane.position(0); for (int i = 0; i < gcdPlane.length;) { byte y1 = yuyvPlane.get(); byte u = yuyvPlane.get(); byte y2 = yuyvPlane.get(); byte v = yuyvPlane.get(); // 11110000 = F0 // 11111100 = FC gcdPlane[i++] = tmap[(y1 & 0xF0) << 8 | (v & 0xFC) << 4 | (u & 0xFC) >>> 2]; gcdPlane[i++] = tmap[(y2 & 0xF0) << 8 | (v & 0xFC) << 4 | (u & 0xFC) >>> 2]; } yuyvPlane.position(0); } private static int clipping(int param, int min, int max) { if (param > max) return max; if (param < min) return min; return param; } }