Updated led simulation (little bit faster and behind a worker to keep gui responsive)

Former-commit-id: 45d6a3d0243f5fb3a0bbcb03f2276e13b683c182
This commit is contained in:
T. van der Zwan 2013-11-15 22:26:31 +01:00
parent e1e88ba2cf
commit 2879f44f08
7 changed files with 612 additions and 350 deletions

View File

@ -1 +1 @@
85ee9ddb3d9a3dd3ba63e1d1d8b21e3616cb79ae
fb506ad21f8aabad449e751a8b48337d61be16eb

View File

@ -1,7 +1,6 @@
package org.hyperion.hypercon.gui;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.io.File;
import java.io.IOException;
@ -64,7 +63,7 @@ public class ConfigPanel extends JPanel {
/** The panel for containing the example 'Hyperion TV' */
private JPanel mTvPanel;
/** The simulated 'Hyperion TV' */
private JHyperionTv mHyperionTv;
private LedSimulationComponent mHyperionTv;
private JTabbedPane mSpecificationTabs = null;
/** The left (WEST) side panel containing the diferent configuration panels */
@ -148,7 +147,7 @@ public class ConfigPanel extends JPanel {
mTvPanel = new JPanel();
mTvPanel.setLayout(new BorderLayout());
mHyperionTv = new JHyperionTv();
mHyperionTv = new LedSimulationComponent(ledString.leds);
mTvPanel.add(mHyperionTv, BorderLayout.CENTER);
}
return mTvPanel;

View File

@ -0,0 +1,27 @@
package org.hyperion.hypercon.gui;
import java.awt.Graphics;
import java.awt.Image;
import javax.swing.JComponent;
public class ImageComponent extends JComponent {
private Image mImage;
public ImageComponent() {
super();
}
public void setImage(Image pImage) {
mImage = pImage;
}
@Override
public void paint(Graphics g) {
if (mImage == null) {
return;
}
g.drawImage(mImage, 0, 0, getWidth(), getHeight(), null);
}
}

View File

@ -1,346 +0,0 @@
package org.hyperion.hypercon.gui;
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.font.LineMetrics;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.net.URL;
import java.util.Vector;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ImageIcon;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JPopupMenu;
import javax.swing.SwingWorker;
import org.hyperion.hypercon.spec.Led;
public class JHyperionTv extends Component {
private JPopupMenu mPopupMenu;
private final Action mLoadAction = new AbstractAction("Load image...") {
JFileChooser mImageChooser;
@Override
public void actionPerformed(ActionEvent e) {
if (mImageChooser == null) {
mImageChooser = new JFileChooser();
}
if (mImageChooser.showOpenDialog(JHyperionTv.this) != JFileChooser.APPROVE_OPTION) {
return;
}
File file = mImageChooser.getSelectedFile();
try {
ImageIcon imageIcon = new ImageIcon(file.getAbsolutePath());
Image image = imageIcon.getImage();
mRawImage = image;
repaint();
} catch (Exception ex) {
}
}
};
private class SelectImageAction extends AbstractAction {
private final String mImageName;
SelectImageAction(String pImageName) {
super(pImageName);
mImageName = pImageName;
ImageIcon image = loadImage();
if (image != null) {
Image scaledImage = image.getImage().getScaledInstance(32, 18, Image.SCALE_SMOOTH);
ImageIcon scaledIcon = new ImageIcon(scaledImage, mImageName);
putValue(SMALL_ICON, scaledIcon);
}
}
@Override
public void actionPerformed(ActionEvent e) {
ImageIcon imageIcon = loadImage();
if (imageIcon != null) {
mRawImage = imageIcon.getImage();
repaint();
}
}
ImageIcon loadImage() {
URL imageUrl = JHyperionTv.class.getResource(mImageName + ".png");
if (imageUrl == null) {
System.out.println("Failed to load image: " + mImageName);
return null;
}
return new ImageIcon(imageUrl);
}
}
private synchronized JPopupMenu getPopupMenu() {
if (mPopupMenu == null) {
mPopupMenu = new JPopupMenu();
mPopupMenu.add(mLoadAction);
JMenu selectMenu = new JMenu("Select Image");
selectMenu.add(new SelectImageAction("TestImage_01"));
selectMenu.add(new SelectImageAction("TestImage_02"));
selectMenu.add(new SelectImageAction("TestImage_03"));
selectMenu.add(new SelectImageAction("TestImage_04"));
selectMenu.add(new SelectImageAction("TestImage_05"));
selectMenu.add(new SelectImageAction("TestImageBBB_01"));
selectMenu.add(new SelectImageAction("TestImageBBB_02"));
selectMenu.add(new SelectImageAction("TestImageBBB_03"));
mPopupMenu.add(selectMenu);
}
return mPopupMenu;
}
private Image mRawImage = new ImageIcon(JHyperionTv.class.getResource("TestImage_01.png")).getImage();
int lightBorder = 100;
int tvBorder = 12;
private class LedWrapper {
public final Led led;
public int lastX = 0;
public int lastY = 0;
public LedWrapper(Led pLed) {
led = pLed;
}
}
private final Vector<LedWrapper> mLeds2 = new Vector<>();
public void setLeds(Vector<Led> pLeds) {
mLeds2.clear();
for (Led led : pLeds) {
mLeds2.add(new LedWrapper(led));
}
}
LedWrapper mSelLed = null;
public JHyperionTv() {
// Pre-cache the popup menu
new SwingWorker<Object, Object>() {
@Override
protected Object doInBackground() throws Exception {
return getPopupMenu();
}
}.execute();
addMouseMotionListener(new MouseMotionListener() {
@Override
public void mouseMoved(MouseEvent e) {
mSelLed = null;
double x = (double)(e.getX() - lightBorder - tvBorder) / (getWidth() - lightBorder*2-tvBorder*2);
double y = (double)(e.getY() - lightBorder - tvBorder) / (getHeight() - lightBorder*2-tvBorder*2);
for (LedWrapper led : mLeds2) {
if (led.led.mImageRectangle.contains(x, y) || (Math.abs(led.led.mLocation.getX() - x) < 0.01 && Math.abs(led.led.mLocation.getY() - y) < 0.01)) {
mSelLed = led;
break;
}
}
repaint();
}
@Override
public void mouseDragged(MouseEvent e) {
}
});
addMouseListener(new MouseAdapter() {
@Override
public void mouseReleased(MouseEvent e) {
showPopup(e);
}
@Override
public void mousePressed(MouseEvent e) {
showPopup(e);
}
private void showPopup(MouseEvent e) {
if (!e.isPopupTrigger()) {
return;
}
getPopupMenu().show(JHyperionTv.this, e.getX(), e.getY());
}
});
}
@Override
public void paint(Graphics g) {
super.paint(g);
if (getWidth() <= 2*lightBorder+2*tvBorder+10 || getHeight() <= 2*lightBorder+2*tvBorder+10) {
return;
}
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.BLACK);
g2d.fillRect(0, 0, getWidth(), getHeight());
int screenWidth = getWidth() - 2*lightBorder;
int screenHeight = getHeight() - 2*lightBorder;
int imageWidth = screenWidth - 2*tvBorder;
int imageHeight = screenHeight- 2*tvBorder;
g2d.translate((getWidth() - imageWidth)/2, (getHeight() - imageHeight)/2);
BufferedImage image = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_RGB);
image.getGraphics().drawImage(mRawImage, 0, 0, image.getWidth(), image.getHeight(), null);
if (mLeds2 != null) {
paintAllLeds(g2d, screenWidth, screenHeight, image);
}
g2d.setColor(Color.DARK_GRAY.darker());
g2d.fillRect(-tvBorder, -tvBorder, screenWidth, screenHeight);
g2d.drawImage(image, 0, 0, imageWidth, imageHeight, this);
paintLedNumbers(g2d);
for (LedWrapper led : mLeds2) {
g2d.setColor(Color.GRAY);
int xmin = (int)(led.led.mImageRectangle.getMinX() * (imageWidth-1));
int xmax = (int)(led.led.mImageRectangle.getMaxX()* (imageWidth-1));
int ymin = (int)(led.led.mImageRectangle.getMinY() * (imageHeight-1));
int ymax = (int)(led.led.mImageRectangle.getMaxY() * (imageHeight-1));
g2d.drawRect(xmin, ymin, (xmax-xmin), (ymax-ymin));
}
if (mSelLed != null) {
g2d.setStroke(new BasicStroke(3.0f));
g2d.setColor(Color.WHITE);
int xmin = (int)(mSelLed.led.mImageRectangle.getMinX() * (imageWidth-1));
int xmax = (int)(mSelLed.led.mImageRectangle.getMaxX()* (imageWidth-1));
int ymin = (int)(mSelLed.led.mImageRectangle.getMinY() * (imageHeight-1));
int ymax = (int)(mSelLed.led.mImageRectangle.getMaxY() * (imageHeight-1));
g2d.drawRect(xmin, ymin, (xmax-xmin), (ymax-ymin));
}
Graphics2D gCopy = (Graphics2D)g.create();
gCopy.setXORMode(Color.WHITE);
gCopy.setFont(gCopy.getFont().deriveFont(20.0f));
String ledCntStr = "Led count: " + mLeds2.size();
gCopy.drawString(ledCntStr, getWidth()-150.0f, getHeight()-10.0f);
}
class LedPaint {
int xmin;
int xmax;
int ymin;
int ymax;
int color;
int seqNr;
int screenX;
int screenY;
double angle_rad;
}
private void paintAllLeds(Graphics2D g2d, int screenWidth, int screenHeight, BufferedImage image) {
Dimension screenDimension = new Dimension(getWidth()-2*lightBorder-2*tvBorder, getHeight()-2*lightBorder-2*tvBorder);
int imageWidth = image.getWidth();
int imageHeight = image.getHeight();
Vector<LedPaint> ledPaints = new Vector<>();
for (LedWrapper led : mLeds2) {
LedPaint ledPaint = new LedPaint();
ledPaint.xmin = (int)(led.led.mImageRectangle.getMinX() * (imageWidth-1));
ledPaint.xmax = (int)(led.led.mImageRectangle.getMaxX()* (imageWidth-1));
ledPaint.ymin = (int)(led.led.mImageRectangle.getMinY() * (imageHeight-1));
ledPaint.ymax = (int)(led.led.mImageRectangle.getMaxY() * (imageHeight-1));
int red = 0;
int green = 0;
int blue = 0;
int count = 0;
for (int y = ledPaint.ymin; y <= ledPaint.ymax; ++y) {
for (int x = ledPaint.xmin; x <= ledPaint.xmax; ++x) {
int color = image.getRGB(x, y);
red += (color >> 16) & 0xFF;
green += (color >> 8) & 0xFF;
blue += color & 0xFF;
++count;
}
}
ledPaint.color = count > 0 ? new Color(red / count, green/count, blue/count).getRGB() : 0;
ledPaints.add(ledPaint);
led.lastX = (int) (screenDimension.width * led.led.mLocation.getX());
led.lastY = (int) (screenDimension.height * led.led.mLocation.getY());
ledPaint.screenX = led.lastX;
ledPaint.screenY = led.lastY;
ledPaint.angle_rad = 0.5*Math.PI - led.led.mSide.getAngle_rad();
ledPaint.seqNr = led.led.mLedSeqNr;
}
for (int i=2; i<=180; i+=4) {
int arcSize = 24 + (int)((i/12.0)*(i/12.0));
for(LedPaint led : ledPaints) {
int argb = 0x05000000 | (0x00ffffff & led.color);
g2d.setColor(new Color(argb , true));
g2d.translate(led.screenX, led.screenY);
g2d.rotate(led.angle_rad);
g2d.fillArc(-arcSize, -arcSize, 2*arcSize, 2*arcSize, 90-(i/2), i);
g2d.rotate(-led.angle_rad);
g2d.translate(-led.screenX, -led.screenY);
}
}
}
private void paintLedNumbers(Graphics2D pG2d) {
pG2d.setColor(Color.GRAY);
FontMetrics fontMetrics = pG2d.getFontMetrics();
for (LedWrapper led : mLeds2) {
String seqNrStr = "" + led.led.mLedSeqNr;
Rectangle2D rect = fontMetrics.getStringBounds(seqNrStr, pG2d);
pG2d.drawString("" + led.led.mLedSeqNr, (int)(led.lastX-rect.getWidth()/2), (int)(led.lastY+rect.getHeight()/2-2));
}
}
public static void main(String[] pArgs) {
JFrame frame = new JFrame();
frame.setSize(640, 480);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().setLayout(new BorderLayout());
frame.getContentPane().add(new JHyperionTv());
frame.setVisible(true);
}
}

View File

@ -0,0 +1,313 @@
package org.hyperion.hypercon.gui;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.net.URL;
import java.util.Vector;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ImageIcon;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JProgressBar;
import org.hyperion.hypercon.LedFrameFactory;
import org.hyperion.hypercon.spec.ImageProcessConfig;
import org.hyperion.hypercon.spec.Led;
import org.hyperion.hypercon.spec.LedFrameConstruction;
public class LedSimulationComponent extends JPanel {
private double mBorderFraction = 0.2;
private BufferedImage mTvImage = new BufferedImage(640, 480, BufferedImage.TYPE_INT_ARGB);
private void setImage(Image pImage) {
mTvImage.createGraphics().drawImage(pImage, 0, 0, mTvImage.getWidth(), mTvImage.getHeight(), null);
}
{
Image image = new ImageIcon(LedSimulationComponent.class.getResource("TestImage_01.png")).getImage();
mTvImage.createGraphics().drawImage(image, 0, 0, mTvImage.getWidth(), mTvImage.getHeight(), null);
}
private JPanel mTopPanel;
private ImageComponent mTopLeftImage;
private ImageComponent mTopImage;
private ImageComponent mTopRightImage;
private ImageComponent mLeftImage;
private ImageComponent mRightImage;
private JPanel mBottomPanel;
private ImageComponent mBottomLeftImage;
private ImageComponent mBottomImage;
private ImageComponent mBottomRightImage;
private JProgressBar mProgressBar;
LedTvComponent mTvComponent;
public LedSimulationComponent(Vector<Led> pLeds) {
super();
initialise(pLeds);
setLeds(pLeds);
}
void initialise(Vector<Led> pLeds) {
setBackground(Color.BLACK);
setLayout(new BorderLayout());
add(getTopPanel(), BorderLayout.NORTH);
mLeftImage = new ImageComponent();
mLeftImage.setPreferredSize(new Dimension(100,100));
add(mLeftImage, BorderLayout.WEST);
mRightImage = new ImageComponent();
mRightImage.setPreferredSize(new Dimension(100,100));
add(mRightImage, BorderLayout.EAST);
add(getBottomPanel(), BorderLayout.SOUTH);
mTvComponent = new LedTvComponent(pLeds);
mTvComponent.setImage(mTvImage);
add(mTvComponent, BorderLayout.CENTER);
mTvComponent.addMouseListener(mPopupListener);
}
private JPanel getTopPanel() {
mTopPanel = new JPanel();
mTopPanel.setPreferredSize(new Dimension(100,100));
mTopPanel.setBackground(Color.BLACK);
mTopPanel.setLayout(new BorderLayout());
mTopLeftImage = new ImageComponent();
mTopLeftImage.setPreferredSize(new Dimension(100,100));
mTopPanel.add(mTopLeftImage, BorderLayout.WEST);
mTopImage = new ImageComponent();
mTopPanel.add(mTopImage, BorderLayout.CENTER);
mTopRightImage = new ImageComponent();
mTopRightImage.setPreferredSize(new Dimension(100,100));
mTopPanel.add(mTopRightImage, BorderLayout.EAST);
return mTopPanel;
}
private JPanel getBottomPanel() {
mBottomPanel = new JPanel();
mBottomPanel.setPreferredSize(new Dimension(100,100));
mBottomPanel.setBackground(Color.BLACK);
mBottomPanel.setLayout(new BorderLayout());
mBottomLeftImage = new ImageComponent();
mBottomLeftImage.setPreferredSize(new Dimension(100,100));
mBottomPanel.add(mBottomLeftImage, BorderLayout.WEST);
mBottomImage = new ImageComponent();
mBottomPanel.add(mBottomImage, BorderLayout.CENTER);
mBottomRightImage = new ImageComponent();
mBottomRightImage.setPreferredSize(new Dimension(100,100));
mBottomPanel.add(mBottomRightImage, BorderLayout.EAST);
mProgressBar = new JProgressBar(0, 100);
mBottomPanel.add(mProgressBar, BorderLayout.SOUTH);
return mBottomPanel;
}
LedSimulationWorker mWorker = null;
public void setLeds(Vector<Led> pLeds) {
mTvComponent.setLeds(pLeds);
synchronized (LedSimulationComponent.this) {
if (mWorker != null) {
mWorker.cancel(true);
}
mWorker = null;
}
mWorker = new LedSimulationWorker(mTvImage, pLeds);
mProgressBar.setValue(0);
mWorker.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
BufferedImage backgroundImage = null;
synchronized(LedSimulationComponent.this) {
if (mWorker == null) {
return;
}
if (evt.getPropertyName() == "progress") {
mProgressBar.setValue(mWorker.getProgress());
return;
}
if (!mWorker.isDone()) {
return;
}
try {
backgroundImage = mWorker.get();
mWorker = null;
} catch (Exception e) {}
}
if (backgroundImage == null) {
return;
}
int width = backgroundImage.getWidth();
int height = backgroundImage.getHeight();
int borderWidth = (int) (backgroundImage.getWidth() * mBorderFraction);
int borderHeight = (int) (backgroundImage.getHeight() * mBorderFraction);
mTopLeftImage.setImage(backgroundImage.getSubimage(0, 0, borderWidth, borderHeight));
mTopImage.setImage(backgroundImage.getSubimage(borderWidth, 0, width-2*borderWidth, borderHeight));
mTopRightImage.setImage(backgroundImage.getSubimage(width-borderWidth, 0, borderWidth, borderHeight));
mLeftImage.setImage(backgroundImage.getSubimage(0, borderHeight, borderWidth, height-2*borderHeight));
mRightImage.setImage(backgroundImage.getSubimage(width-borderWidth, borderHeight, borderWidth, height-2*borderHeight));
mBottomLeftImage.setImage(backgroundImage.getSubimage(0, height-borderHeight, borderWidth, borderHeight));
mBottomImage.setImage(backgroundImage.getSubimage(borderWidth, height-borderHeight, width-2*borderWidth, borderHeight));
mBottomRightImage.setImage(backgroundImage.getSubimage(width-borderWidth, height-borderHeight, borderWidth, borderHeight));
mProgressBar.setValue(100);
mWorker = null;
LedSimulationComponent.this.repaint();
}
});
mWorker.execute();
}
public static void main(String[] pArgs) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setSize(800, 600);
Vector<Led> leds = LedFrameFactory.construct(new LedFrameConstruction(), new ImageProcessConfig());
LedSimulationComponent ledSimComp = new LedSimulationComponent(leds);
frame.getContentPane().setLayout(new BorderLayout());
frame.getContentPane().add(ledSimComp);
frame.setVisible(true);
}
private final MouseListener mPopupListener = new MouseAdapter() {
@Override
public void mouseReleased(MouseEvent e) {
showPopup(e);
}
@Override
public void mousePressed(MouseEvent e) {
showPopup(e);
}
private void showPopup(MouseEvent e) {
if (!e.isPopupTrigger()) {
return;
}
getPopupMenu().show(mTvComponent, e.getX(), e.getY());
}
};
private JPopupMenu mPopupMenu;
private final Action mLoadAction = new AbstractAction("Load image...") {
JFileChooser mImageChooser;
@Override
public void actionPerformed(ActionEvent e) {
if (mImageChooser == null) {
mImageChooser = new JFileChooser();
}
if (mImageChooser.showOpenDialog(mTvComponent) != JFileChooser.APPROVE_OPTION) {
return;
}
File file = mImageChooser.getSelectedFile();
try {
ImageIcon imageIcon = new ImageIcon(file.getAbsolutePath());
Image image = imageIcon.getImage();
mTvComponent.setImage(image);
// setIma
} catch (Exception ex) {
}
}
};
private synchronized JPopupMenu getPopupMenu() {
if (mPopupMenu == null) {
mPopupMenu = new JPopupMenu();
mPopupMenu.add(mLoadAction);
JMenu selectMenu = new JMenu("Select Image");
selectMenu.add(new SelectImageAction("TestImage_01"));
selectMenu.add(new SelectImageAction("TestImage_02"));
selectMenu.add(new SelectImageAction("TestImage_03"));
selectMenu.add(new SelectImageAction("TestImage_04"));
selectMenu.add(new SelectImageAction("TestImage_05"));
selectMenu.add(new SelectImageAction("TestImageBBB_01"));
selectMenu.add(new SelectImageAction("TestImageBBB_02"));
selectMenu.add(new SelectImageAction("TestImageBBB_03"));
mPopupMenu.add(selectMenu);
}
return mPopupMenu;
}
private class SelectImageAction extends AbstractAction {
private final String mImageName;
SelectImageAction(String pImageName) {
super(pImageName);
mImageName = pImageName;
ImageIcon image = loadImage();
if (image != null) {
Image scaledImage = image.getImage().getScaledInstance(32, 18, Image.SCALE_SMOOTH);
ImageIcon scaledIcon = new ImageIcon(scaledImage, mImageName);
putValue(SMALL_ICON, scaledIcon);
}
}
@Override
public void actionPerformed(ActionEvent e) {
ImageIcon imageIcon = loadImage();
if (imageIcon != null) {
Image image = imageIcon.getImage();
setImage(image);
mTvComponent.setImage(image);
repaint();
}
}
ImageIcon loadImage() {
URL imageUrl = LedSimulationComponent.class.getResource(mImageName + ".png");
if (imageUrl == null) {
System.out.println("Failed to load image: " + mImageName);
return null;
}
return new ImageIcon(imageUrl);
}
}
}

View File

@ -0,0 +1,135 @@
package org.hyperion.hypercon.gui;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.util.List;
import java.util.Vector;
import javax.swing.SwingWorker;
import org.hyperion.hypercon.spec.Led;
public class LedSimulationWorker extends SwingWorker<BufferedImage, Object> {
private final double mBorderFraction = 0.2;
private final BufferedImage mTvImage;
private final Vector<Led> mLeds;
public LedSimulationWorker(BufferedImage pTvImage, Vector<Led> pLeds) {
super();
mTvImage = pTvImage;
mLeds = pLeds;
}
class LedPaint {
int color;
Point point;
double angle_rad;
}
private final List<LedPaint> mLedPaints = new Vector<>();
@Override
protected BufferedImage doInBackground() throws Exception {
Dimension imageDim = new Dimension(1280, 720);
BufferedImage backgroundImage = new BufferedImage(imageDim.width, imageDim.height, BufferedImage.TYPE_INT_ARGB);
mLedPaints.clear();
setProgress(5);
int imageWidth = mTvImage.getWidth();
int imageHeight = mTvImage.getHeight();
for (Led led : mLeds) {
LedPaint ledPaint = new LedPaint();
// Determine the location and orientation of the led on the image
ledPaint.point = tv2image(imageDim, led.mLocation);
ledPaint.angle_rad = 0.5*Math.PI - led.mSide.getAngle_rad();
// Determine the color of the led
int xMin = (int)(led.mImageRectangle.getMinX() * (imageWidth-1));
int xMax = (int)(led.mImageRectangle.getMaxX() * (imageWidth-1));
int yMin = (int)(led.mImageRectangle.getMinY() * (imageHeight-1));
int yMax = (int)(led.mImageRectangle.getMaxY() * (imageHeight-1));
ledPaint.color = determineColor(xMin, xMax, yMin, yMax);
mLedPaints.add(ledPaint);
}
setProgress(10);
Graphics2D g2d = backgroundImage.createGraphics();
// Clear the image with a black rectangle
g2d.setColor(Color.BLACK);
g2d.drawRect(0, 0, backgroundImage.getWidth(), backgroundImage.getHeight());
paintAllLeds(g2d);
return backgroundImage;
}
Point tv2image(Dimension pImageDim, Point2D point) {
double tvFraction = (1.0 - 2*mBorderFraction);
double tvWidth = tvFraction * pImageDim.width;
double tvXIndex = point.getX()*tvWidth;
double imageXIndex = tvXIndex + mBorderFraction*pImageDim.width;
double tvHeight = tvFraction * pImageDim.height;
double tvYIndex = point.getY()*tvHeight;
double imageYIndex = tvYIndex + mBorderFraction*pImageDim.height;
return new Point((int)imageXIndex, (int)imageYIndex);
}
private int determineColor(int xMin, int xMax, int yMin, int yMax) {
int red = 0;
int green = 0;
int blue = 0;
int count = 0;
for (int y = yMin; y <= yMax; ++y) {
for (int x = xMin; x <= xMax; ++x) {
int color = mTvImage.getRGB(x, y);
red += (color >> 16) & 0xFF;
green += (color >> 8) & 0xFF;
blue += color & 0xFF;
++count;
}
}
return count > 0 ? new Color(red / count, green/count, blue/count).getRGB() : 0;
}
private void paintAllLeds(Graphics2D g2d) {
for (int i=2; i<=180; i+=4) {
if (isCancelled()) {
return;
}
int arcSize = 24 + (int)((i/12.0)*(i/12.0));
for(LedPaint led : mLedPaints) {
int argb = 0x05000000 | (0x00ffffff & led.color);
g2d.setColor(new Color(argb , true));
g2d.translate(led.point.getX(), led.point.getY());
g2d.rotate(led.angle_rad);
g2d.fillArc(-arcSize, -arcSize, 2*arcSize, 2*arcSize, 90-(i/2), i);
g2d.rotate(-led.angle_rad);
g2d.translate(-led.point.getX(), -led.point.getY());
setProgress(10+i/3);
}
}
}
}

View File

@ -0,0 +1,134 @@
package org.hyperion.hypercon.gui;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.util.Vector;
import javax.swing.JComponent;
import org.hyperion.hypercon.spec.Led;
public class LedTvComponent extends JComponent {
private final BufferedImage mDisplayedImage = new BufferedImage(1280, 720, BufferedImage.TYPE_INT_ARGB);
private final Graphics2D mImageG2d = mDisplayedImage.createGraphics();
private final int mBorderWidth = 12;
private Vector<Led> mLeds;
private Led mSelectedLed;
public LedTvComponent(Vector<Led> pLeds) {
mLeds = pLeds;
addMouseMotionListener(mMouseMotionListener);
}
public void setLeds(Vector<Led> pLeds) {
mLeds = pLeds;
}
public void setImage(Image pImage) {
mImageG2d.clearRect(0, 0, mDisplayedImage.getWidth(), mDisplayedImage.getHeight());
mImageG2d.drawImage(pImage, 0,0, mDisplayedImage.getWidth(), mDisplayedImage.getHeight(), null);
}
@Override
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.DARK_GRAY.darker());
g2d.fillRect(0,0, getWidth()-1, getHeight()-1);
g2d.drawImage(mDisplayedImage, mBorderWidth, mBorderWidth, getWidth()-2*mBorderWidth, getHeight()-2*mBorderWidth, null);
if (mLeds == null) {
return;
}
g2d.setColor(Color.GRAY);
for (Led led : mLeds) {
Rectangle rect = led2tv(led.mImageRectangle);
g2d.drawRect(rect.x, rect.y, rect.width, rect.height);
switch (led.mSide) {
case top_left:
g2d.drawString(""+led.mLedSeqNr, 0, 11);
break;
case top:
g2d.drawString(""+led.mLedSeqNr, (int)rect.getCenterX(), 11);
break;
case top_right:
g2d.drawString(""+led.mLedSeqNr, (int)getWidth()-11, (int)11);
break;
case right:
g2d.drawString(""+led.mLedSeqNr, (int)getWidth()-11, (int)rect.getCenterY());
break;
case bottom_right:
g2d.drawString(""+led.mLedSeqNr, (int)getWidth()-11, (int)getHeight()-1);
break;
case bottom:
g2d.drawString(""+led.mLedSeqNr, (int)rect.getCenterX(), (int)getHeight()-1);
break;
case bottom_left:
g2d.drawString(""+led.mLedSeqNr, (int)0, (int)getHeight()-1);
break;
case left:
g2d.drawString(""+led.mLedSeqNr, 0, (int)rect.getCenterY());
break;
}
}
if (mSelectedLed != null) {
Rectangle rect = led2tv(mSelectedLed.mImageRectangle);
g2d.setStroke(new BasicStroke(3.0f));
g2d.setColor(Color.WHITE);
g2d.drawRect(rect.x, rect.y, rect.width, rect.height);
}
}
public Rectangle led2tv(Rectangle2D pLedRect) {
int tvWidth = getWidth()-2*mBorderWidth;
int tvHeight = getHeight()-2*mBorderWidth;
int x = (int) Math.round(mBorderWidth + tvWidth*pLedRect.getX());
int y = (int) Math.round(mBorderWidth + tvHeight*pLedRect.getY());
int width = (int) Math.round(tvWidth * pLedRect.getWidth());
int height = (int) Math.round(tvHeight * pLedRect.getHeight());
return new Rectangle(x,y, width, height);
}
private final MouseMotionListener mMouseMotionListener = new MouseMotionListener() {
@Override
public void mouseMoved(MouseEvent e) {
mSelectedLed = null;
double x = (double)(e.getX() - mBorderWidth) / (getWidth() - mBorderWidth*2);
double y = (double)(e.getY() - mBorderWidth) / (getHeight() - mBorderWidth*2);
for (Led led : mLeds) {
if (led.mImageRectangle.contains(x, y) || (Math.abs(led.mLocation.getX() - x) < 0.01 && Math.abs(led.mLocation.getY() - y) < 0.01)) {
mSelectedLed = led;
break;
}
}
repaint();
}
@Override
public void mouseDragged(MouseEvent e) {
}
};
}