package hueimmersive; import java.awt.Color; import java.awt.Graphics; import java.awt.GraphicsEnvironment; import java.awt.Rectangle; import java.awt.Robot; import java.awt.image.BufferedImage; import javax.swing.ImageIcon; public class ImmersiveProcess { private static Rectangle ScreenSize = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()[Settings.getInteger("screen")].getDefaultConfiguration().getBounds(); public static Rectangle CaptureSize = new Rectangle(0, 0, ScreenSize.width, ScreenSize.height); public static int chunksNumX; public static int chunksNumY; public static final int algorithms = 4; static { setSettings(); } public static void setStandbyOutput() throws Exception { setSettings(); Main.ui.cpi.setStandbyIcon(CaptureSize, chunksNumX, chunksNumY); } private static void setSettings() { // setup screen area double ratio; int x, y, w, h; ScreenSize = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()[Settings.getInteger("screen")].getDefaultConfiguration().getBounds(); switch (Settings.getInteger("format")) { case 0: // Fullscreen ratio = 1.0; w = (int)ScreenSize.getWidth(); h = (int)ScreenSize.getHeight(); x = 0; y = 0; break; case 1: // 16:9 ratio = 9.0 / 16.0; w = (int)ScreenSize.getWidth(); h = (int)(ratio * ScreenSize.getWidth()); x = 0; y = (int)((ScreenSize.getHeight() - h) / 2); break; case 2: // 21:9 (Cinema) ratio = 9.0 / 21.0; w = (int)(ScreenSize.getWidth()); h = (int)(ratio * ScreenSize.getWidth()); x = 0; y = (int)((ScreenSize.getHeight() - h) / 2); break; case 3: // Borderless (Windows) ratio = 1.0; w = (int)ScreenSize.getWidth(); h = (int)(ScreenSize.getHeight() - 40 - 23); x = 0; y = 23; break; case 4: // 4:3 ratio = 3.0 / 4.0; w = (int)(ratio * ScreenSize.getWidth()); h = (int)ScreenSize.getHeight(); x = (int)((ScreenSize.getWidth() - w) / 2); y = 0; break; default: ratio = 1.0; w = (int)ScreenSize.getWidth(); h = (int)ScreenSize.getHeight(); x = 0; y = 0; break; } CaptureSize = new Rectangle((int)ScreenSize.getX() + x, (int)ScreenSize.getY() + y, w, h); // calculate number of chunks double chunks = Settings.getInteger("chunks"); chunks = 3 + 0.35 * Math.pow(chunks, 1.4); chunksNumX = (int) Math.round(chunks); chunksNumY = (int) Math.round(((double)CaptureSize.height / (double)CaptureSize.width) * chunksNumX); //round -> exact | ceil (round up) -> less options, always transverse | nothing (round down) -> imprecise } public static void execute() throws Exception // execute the process to get immersive colors based on the captured area { applyChanges(); capture(); } private static int lFormat = Settings.getInteger("format"); private static int lChunks = Settings.getInteger("chunks"); private static int lScreen = Settings.getInteger("screen"); private static boolean forceStandbyColorGrid = false; private static void applyChanges() throws Exception // apply changed settings { forceStandbyColorGrid = false; if (Settings.getInteger("format") != lFormat || Settings.getInteger("chunks") != lChunks || Settings.getInteger("screen") != lScreen) { lFormat = Settings.getInteger("format"); lChunks = Settings.getInteger("chunks"); lScreen = Settings.getInteger("screen"); setSettings(); Main.ui.cpi.setStandbyIcon(CaptureSize, chunksNumX, chunksNumY); forceStandbyColorGrid = true; } } private static void capture() throws Exception // capture a selected screen area { BufferedImage screenshot = new Robot().createScreenCapture(CaptureSize); chunking(screenshot); } private static void chunking(BufferedImage screenshot) throws Exception // split the image in serval chunks { int chunkResX = screenshot.getWidth() / chunksNumX; int chunkResY = screenshot.getHeight() / chunksNumY; BufferedImage[] chunks = new BufferedImage[chunksNumX * chunksNumY]; int id = 0; for (int x = 0; x < chunksNumX; x++) { for (int y = 0; y < chunksNumY; y++) { chunks[id] = screenshot.getSubimage(chunkResX * x, chunkResY * y, chunkResX, chunkResY); id++; } } avgChunks(chunks); } private static void avgChunks(BufferedImage[] chunks) throws Exception // get average color of each chunk { Color[] avgColors = new Color[chunks.length]; for (int i = 0; i < chunks.length; i++) { int avgR = 0; int avgG = 0; int avgB = 0; for (int x = 0; x < chunks[i].getWidth(); x++) { for (int y = 0; y < chunks[i].getHeight(); y++) { Color pColor = new Color(chunks[i].getRGB(x, y)); avgR += pColor.getRed(); avgG += pColor.getGreen(); avgB += pColor.getBlue(); } } avgR = avgR / (chunks[i].getWidth() * chunks[i].getHeight()); avgG = avgG / (chunks[i].getWidth() * chunks[i].getHeight()); avgB = avgB / (chunks[i].getWidth() * chunks[i].getHeight()); avgColors[i] = new Color(avgR, avgG, avgB); } if (Main.ui.cpi.frame.isVisible()) { drawColorGrid(avgColors); } analyze(avgColors); } private static void drawColorGrid(Color[] ColorContainer) // draw the chunks in the color grid interface { if (forceStandbyColorGrid == false) { int ChunkResX = (int)(CaptureSize.getWidth() / 3) / chunksNumX; int ChunkResY = (int)(CaptureSize.getHeight() / 3) / chunksNumY; BufferedImage b = new BufferedImage(ChunkResX * chunksNumX, ChunkResY * chunksNumY, BufferedImage.TYPE_INT_RGB); Graphics g = b.createGraphics(); int i = 0; for (int x = 0; x < chunksNumX; x++) { for (int y = 0; y < chunksNumY; y++) { g.setColor(ColorContainer[i]); g.drawRect(x * ChunkResX, y * ChunkResY, ChunkResX, ChunkResY); g.fillRect(x * ChunkResX, y * ChunkResY, ChunkResX, ChunkResY); i++; } } Main.ui.cpi.label_Colors.setIcon(new ImageIcon(b)); Main.ui.cpi.frame.pack(); } } private static void analyze(Color[] colorcontainer) throws Exception // analyze all chunks { float[] temp_color; float[] avg_color = Color.RGBtoHSB(0, 0, 0, null); float[] sat_color = Color.RGBtoHSB(0, 0, 0, null); float[] bri_color = Color.RGBtoHSB(0, 0, 0, null); float[] dar_color = Color.RGBtoHSB(0, 0, 0, null); float minSat = 1; float maxSat = 0; float minBri = 1; float maxBri = 0; int[] avg_rgb = new int[3]; for (Color color : colorcontainer) // get average color { temp_color = Color.RGBtoHSB(color.getRed(), color.getGreen(), color.getBlue(), null); if (temp_color[1] <= minSat) { minSat = temp_color[1]; } if (temp_color[1] >= maxSat) { maxSat = temp_color[1]; } if (temp_color[2] <= minBri) { minBri = temp_color[2]; } if (temp_color[2] >= maxBri) { maxBri = temp_color[2]; } avg_rgb[0] += color.getRed(); avg_rgb[1] += color.getGreen(); avg_rgb[2] += color.getBlue(); } avg_rgb[0] = avg_rgb[0] / colorcontainer.length; avg_rgb[1] = avg_rgb[1] / colorcontainer.length; avg_rgb[2] = avg_rgb[2] / colorcontainer.length; avg_color = Color.RGBtoHSB(avg_rgb[0], avg_rgb[1], avg_rgb[2], null); for (Color color : colorcontainer) // get max/min sat/bri { temp_color = Color.RGBtoHSB(color.getRed(), color.getGreen(), color.getBlue(), null); if (temp_color[2] >= ((maxBri - minBri) / 2) + minBri) { bri_color[0] = (bri_color[0] + temp_color[0]) / 2; bri_color[1] = (bri_color[1] + temp_color[1]) / 2; bri_color[2] = (bri_color[2] + temp_color[2]) / 2; } if (temp_color[2] <= ((maxBri - minBri) / 2) + minBri) { dar_color[0] = (dar_color[0] + temp_color[0]) / 2; dar_color[1] = (dar_color[1] + temp_color[1]) / 2; dar_color[2] = (dar_color[2] + temp_color[2]) / 2; } if (temp_color[1] >= sat_color[1] && temp_color[2] >= ((maxBri - minBri) / 3 + minBri)) // ((maxBri - minBri) / 2 + minBri)) { sat_color = temp_color; } /*if (temp_color[1] >= sat_color[1] && temp_color[2] >= avg_color[2]) { sat_color = temp_color; }*/ } Color[] extrColor = new Color[algorithms]; extrColor[0] = Color.getHSBColor(avg_color[0], avg_color[1], avg_color[2]); extrColor[1] = Color.getHSBColor(sat_color[0], sat_color[1], sat_color[2]); extrColor[2] = Color.getHSBColor(bri_color[0], bri_color[1], bri_color[2]); extrColor[3] = Color.getHSBColor(dar_color[0], dar_color[1], dar_color[2]); setLightColor(extrColor); } private static void setLightColor(Color[] extrColor) throws Exception // distribute the colors to the lights { for (HLight light : HBridge.lights) { boolean active = Settings.Light.getActive(light); int alg = Settings.Light.getAlgorithm(light); if(active) { Main.hueControl.setLight(light, extrColor[alg]); } } } }