2 * Copyright (c) 2010-2022 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
14 package org.openhab.binding.nanoleaf.internal.layout;
16 import java.awt.Color;
17 import java.awt.Graphics2D;
18 import java.awt.RenderingHints;
19 import java.awt.image.BufferedImage;
20 import java.io.ByteArrayOutputStream;
21 import java.io.IOException;
22 import java.util.List;
24 import javax.imageio.ImageIO;
26 import org.eclipse.jdt.annotation.NonNullByDefault;
27 import org.openhab.binding.nanoleaf.internal.NanoleafBindingConstants;
28 import org.openhab.binding.nanoleaf.internal.layout.shape.Panel;
29 import org.openhab.binding.nanoleaf.internal.layout.shape.PanelFactory;
30 import org.openhab.binding.nanoleaf.internal.model.GlobalOrientation;
31 import org.openhab.binding.nanoleaf.internal.model.Layout;
32 import org.openhab.binding.nanoleaf.internal.model.PanelLayout;
33 import org.openhab.binding.nanoleaf.internal.model.PositionDatum;
36 * Renders the Nanoleaf layout to an image.
38 * @author Jørgen Austvik - Initial contribution
41 public class NanoleafLayout {
43 private static final Color COLOR_BACKGROUND = Color.WHITE;
45 public static byte[] render(PanelLayout panelLayout, PanelState state, LayoutSettings settings) throws IOException {
46 double rotationRadians = 0;
47 GlobalOrientation globalOrientation = panelLayout.getGlobalOrientation();
48 if (globalOrientation != null) {
49 rotationRadians = calculateRotationRadians(globalOrientation);
52 Layout layout = panelLayout.getLayout();
57 List<PositionDatum> positionDatums = layout.getPositionData();
58 if (positionDatums == null) {
62 ImagePoint2D size[] = findSize(positionDatums, rotationRadians);
63 final ImagePoint2D min = size[0];
64 final ImagePoint2D max = size[1];
66 BufferedImage image = new BufferedImage(
67 (max.getX() - min.getX()) + 2 * NanoleafBindingConstants.LAYOUT_BORDER_WIDTH,
68 (max.getY() - min.getY()) + 2 * NanoleafBindingConstants.LAYOUT_BORDER_WIDTH,
69 BufferedImage.TYPE_INT_RGB);
70 Graphics2D g2 = image.createGraphics();
71 g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
72 g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
73 g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
75 g2.setBackground(COLOR_BACKGROUND);
76 g2.clearRect(0, 0, image.getWidth(), image.getHeight());
78 DrawingSettings dc = new DrawingSettings(settings, image.getHeight(), min, rotationRadians);
79 List<Panel> panels = PanelFactory.createPanels(positionDatums);
80 for (Panel panel : panels) {
81 panel.draw(g2, dc, state);
84 ByteArrayOutputStream out = new ByteArrayOutputStream();
85 ImageIO.write(image, "png", out);
86 return out.toByteArray();
89 private static double calculateRotationRadians(GlobalOrientation globalOrientation) {
90 Integer maxObj = globalOrientation.getMax();
91 int maxValue = maxObj == null ? 360 : (int) maxObj;
92 int value = globalOrientation.getValue(); // 0 - 360 measured counter clockwise.
93 return ((double) (maxValue - value)) * (Math.PI / 180);
96 private static ImagePoint2D[] findSize(List<PositionDatum> positionDatums, double rotationRadians) {
102 List<Panel> panels = PanelFactory.createPanels(positionDatums);
103 for (Panel shape : panels) {
104 for (Point2D point : shape.generateOutline()) {
105 var rotated = point.rotate(rotationRadians);
106 maxX = Math.max(rotated.getX(), maxX);
107 maxY = Math.max(rotated.getY(), maxY);
108 minX = Math.min(rotated.getX(), minX);
109 minY = Math.min(rotated.getY(), minY);
113 return new ImagePoint2D[] { new ImagePoint2D(minX, minY), new ImagePoint2D(maxX, maxY) };